@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,153 @@
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
+
10
+ SKILLS_ROOT = Path(__file__).resolve().parents[3]
11
+ SCRIPT = "service-omni-supervisor-config-deploy/scripts/deploy-and-report.sh"
12
+
13
+ _FAKE_SF = r'''#!/usr/bin/env bash
14
+ sub="${1:-} ${2:-}"; args="$*"
15
+ state_dir="${FAKE_STATE_DIR:?}"
16
+ deployed="$state_dir/deployed"
17
+ actions="$state_dir/actions"
18
+ tabs="$state_dir/tabs"
19
+ trace="$state_dir/trace"
20
+ capture_xml="$state_dir/deployed.xml"
21
+ capture_package="$state_dir/package.xml"
22
+ config_dn="${FAKE_CONFIG_DN:-Omni_Supervisor}"
23
+
24
+ emit_surface() {
25
+ local kind="$1" source_file="$2" initial_json="$3" field="$4"
26
+ if [ ! -f "$deployed" ]; then
27
+ printf '%s' "$initial_json" | jq -c --arg field "$field" '
28
+ to_entries | {status:0,result:{records:map({($field):.value,DisplayOrder:(.key+1)})}}'
29
+ return
30
+ fi
31
+ if [ ! -s "$source_file" ]; then
32
+ echo '{"status":0,"result":{"records":[]}}'
33
+ return
34
+ fi
35
+ jq -R -s -c --arg field "$field" '
36
+ split("\n") | map(select(length>0)) | to_entries |
37
+ {status:0,result:{records:map({($field):.value,DisplayOrder:(.key+1)})}}' "$source_file"
38
+ }
39
+
40
+ case "$sub" in
41
+ "org display") echo '{"status":0,"result":{"id":"00Dxx0000000000EAA"}}';;
42
+ "org list") echo '{"status":0,"result":[]}' ;;
43
+ "data query")
44
+ printf '%s\n' "$args" >> "$trace"
45
+ if printf '%s' "$args" | grep -q "FROM Organization"; then
46
+ echo '{"status":0,"result":{"records":[{"Id":"00Dxx0000000000EAA","IsSandbox":true,"TrialExpirationDate":null,"OrganizationType":"Developer Edition"}]}}'
47
+ elif printf '%s' "$args" | grep -q "FROM User"; then
48
+ echo '{"status":0,"result":{"records":[{"Id":"005xx0000000001AAA","Username":"supervisor1.0000000e@example.com","Profile":{"Name":"Standard User"}}]}}'
49
+ elif printf '%s' "$args" | grep -q "FROM Group"; then
50
+ echo '{"status":0,"result":{"records":[{"Id":"00Gxx0000000001AAA"}]}}'
51
+ elif printf '%s' "$args" | grep -q "FROM OmniSupervisorConfigAction"; then
52
+ emit_surface action "$actions" "${FAKE_EXIST_ACTIONS:-[]}" OmniSupervisorActionType
53
+ elif printf '%s' "$args" | grep -q "FROM OmniSupervisorConfigTab"; then
54
+ emit_surface tab "$tabs" "${FAKE_EXIST_TABS:-[]}" OmniSupervisorTabType
55
+ elif printf '%s' "$args" | grep -q "FROM OmniSupervisorConfigUser"; then
56
+ echo '{"status":0,"result":{"records":[{"Id":"0Q4xx0000000001AAA"}]}}'
57
+ elif printf '%s' "$args" | grep -q "FROM OmniSupervisorConfigQueue"; then
58
+ echo '{"status":0,"result":{"records":[{"Id":"0Q5xx0000000001AAA"}]}}'
59
+ elif printf '%s' "$args" | grep -q "FROM OmniSupervisorConfig"; then
60
+ printf '{"status":0,"result":{"records":[{"Id":"0Q2xx0000000001AAA","DeveloperName":"%s","MasterLabel":"%s","SkillVisibility":"%s"}]}}' "$config_dn" "${FAKE_MASTER_LABEL:-Existing Supervisor Label}" "${FAKE_SKILL_VISIBILITY:-AnySkill}"
61
+ else
62
+ echo '{"status":0,"result":{"records":[]}}'
63
+ fi;;
64
+ "project deploy")
65
+ if printf '%s' "$args" | grep -q " start "; then
66
+ cp "force-app/main/default/omniSupervisorConfigs/$config_dn.omniSupervisorConfig-meta.xml" "$capture_xml"
67
+ cp package.xml "$capture_package"
68
+ echo '{"status":0,"result":{"id":"0Afxx0000000001AAA"}}'
69
+ else
70
+ : > "$deployed"
71
+ if [ "${FAKE_DEPLOY_PRESERVES_SURFACE:-0}" = "1" ]; then
72
+ printf '%s' "${FAKE_EXIST_ACTIONS:-[]}" | jq -r '.[]' > "$actions"
73
+ printf '%s' "${FAKE_EXIST_TABS:-[]}" | jq -r '.[]' > "$tabs"
74
+ else
75
+ : > "$actions"; : > "$tabs"
76
+ fi
77
+ printf '{"status":0,"result":{"id":"0Afxx0000000001AAA","status":"Succeeded","files":[{"fullName":"%s","type":"OmniSupervisorConfig","state":"Changed"}]}}' "$config_dn"
78
+ fi;;
79
+ "data create")
80
+ printf '%s\n' "$args" >> "$trace"
81
+ if printf '%s' "$args" | grep -q "OmniSupervisorConfigAction"; then
82
+ value=$(printf '%s' "$args" | sed -n 's/.*OmniSupervisorActionType=\([^ ]*\).*/\1/p')
83
+ printf '%s\n' "$value" >> "$actions"
84
+ elif printf '%s' "$args" | grep -q "OmniSupervisorConfigTab"; then
85
+ value=$(printf '%s' "$args" | sed -n 's/.*OmniSupervisorTabType=\([^ ]*\).*/\1/p')
86
+ printf '%s\n' "$value" >> "$tabs"
87
+ fi
88
+ echo '{"status":0,"result":{"id":"0Q3xx0000000001AAA","success":true}}';;
89
+ *) echo '{"status":0,"result":{}}';;
90
+ esac
91
+ '''
92
+
93
+
94
+ def last_json(output: str) -> dict:
95
+ decoder = json.JSONDecoder()
96
+ result, index = None, 0
97
+ while index < len(output):
98
+ if output[index] not in "{[":
99
+ index += 1
100
+ continue
101
+ try:
102
+ candidate, end = decoder.raw_decode(output, index)
103
+ if isinstance(candidate, dict):
104
+ result = candidate
105
+ index = end
106
+ except json.JSONDecodeError:
107
+ index += 1
108
+ assert result is not None, output
109
+ return result
110
+
111
+
112
+ class FakeSf:
113
+ def __init__(self):
114
+ self.root: Path | None = None
115
+ self.bin_dir: Path | None = None
116
+ self.state_dir: Path | None = None
117
+
118
+ def __enter__(self):
119
+ self.root = Path(tempfile.mkdtemp(prefix="supconfig-fake-sf-"))
120
+ self.bin_dir = self.root / "bin"
121
+ self.state_dir = self.root / "state"
122
+ self.bin_dir.mkdir()
123
+ self.state_dir.mkdir()
124
+ executable = self.bin_dir / "sf"
125
+ executable.write_text(_FAKE_SF)
126
+ executable.chmod(0o755)
127
+ return self
128
+
129
+ def run(self, args, extra_env=None):
130
+ assert self.bin_dir is not None and self.state_dir is not None
131
+ env = dict(os.environ)
132
+ env["PATH"] = str(self.bin_dir) + os.pathsep + env.get("PATH", "")
133
+ env["FAKE_STATE_DIR"] = str(self.state_dir)
134
+ if extra_env:
135
+ env.update({key: str(value) for key, value in extra_env.items()})
136
+ proc = subprocess.run(
137
+ ["bash", str(SKILLS_ROOT / SCRIPT), *args],
138
+ capture_output=True,
139
+ text=True,
140
+ env=env,
141
+ cwd=str(SKILLS_ROOT),
142
+ )
143
+ return proc.returncode, (proc.stdout or "") + (proc.stderr or "")
144
+
145
+ def read_state(self, name: str) -> str:
146
+ assert self.state_dir is not None
147
+ path = self.state_dir / name
148
+ return path.read_text() if path.exists() else ""
149
+
150
+ def __exit__(self, *_):
151
+ import shutil
152
+ if self.root:
153
+ shutil.rmtree(self.root, ignore_errors=True)
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env python3
2
+ import json
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+
7
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
8
+ from _bootstrap import FakeSf, last_json # noqa: E402
9
+
10
+
11
+ class PreservationTests(unittest.TestCase):
12
+ def test_update_preserves_existing_surface_and_visibility(self):
13
+ actions = json.dumps(["AllAgents.ChangeQueues", "AllAgents.ChangeSkills"])
14
+ tabs = json.dumps(["Wallboard", "Agents"])
15
+ with FakeSf() as fake:
16
+ rc, output = fake.run(
17
+ ["org", "1", "CaseQueue"],
18
+ {
19
+ "FAKE_EXIST_ACTIONS": actions,
20
+ "FAKE_EXIST_TABS": tabs,
21
+ "FAKE_SKILL_VISIBILITY": "AnySkill",
22
+ },
23
+ )
24
+ deployed_xml = fake.read_state("deployed.xml")
25
+ trace = fake.read_state("trace")
26
+
27
+ self.assertEqual(rc, 0, output)
28
+ self.assertIn("<skillVisibility>AnySkill</skillVisibility>", deployed_xml)
29
+ self.assertIn("OmniSupervisorActionType=AllAgents.ChangeQueues", trace)
30
+ self.assertIn("OmniSupervisorActionType=AllAgents.ChangeSkills", trace)
31
+ self.assertIn("OmniSupervisorTabType=Wallboard", trace)
32
+ self.assertIn("OmniSupervisorTabType=Agents", trace)
33
+ result = last_json(output)
34
+ self.assertEqual(result["skill_visibility"], "AnySkill", output)
35
+ self.assertEqual(result["surface_preservation"]["actions_restored"], 2, output)
36
+ self.assertEqual(result["surface_preservation"]["tabs_restored"], 2, output)
37
+
38
+ def test_explicit_visibility_overrides_existing_value(self):
39
+ with FakeSf() as fake:
40
+ rc, output = fake.run(
41
+ ["org", "1", "CaseQueue", "", "AllSkills"],
42
+ {"FAKE_SKILL_VISIBILITY": "AnySkill"},
43
+ )
44
+ deployed_xml = fake.read_state("deployed.xml")
45
+
46
+ self.assertEqual(rc, 0, output)
47
+ self.assertIn("<skillVisibility>AllSkills</skillVisibility>", deployed_xml)
48
+ self.assertEqual(last_json(output)["skill_visibility"], "AllSkills", output)
49
+
50
+ def test_surface_rows_that_survive_deploy_are_not_inserted_again(self):
51
+ with FakeSf() as fake:
52
+ rc, output = fake.run(
53
+ ["org", "1", "CaseQueue"],
54
+ {
55
+ "FAKE_EXIST_ACTIONS": json.dumps(["AllAgents.ChangeQueues"]),
56
+ "FAKE_EXIST_TABS": json.dumps(["Wallboard"]),
57
+ "FAKE_DEPLOY_PRESERVES_SURFACE": "1",
58
+ },
59
+ )
60
+ trace = fake.read_state("trace")
61
+
62
+ self.assertEqual(rc, 0, output)
63
+ self.assertNotIn("data create", trace)
64
+ self.assertNotIn("OmniSupervisorActionType=", trace)
65
+ self.assertNotIn("OmniSupervisorTabType=", trace)
66
+ result = last_json(output)
67
+ self.assertEqual(result["surface_preservation"]["actions_restored"], 0, output)
68
+ self.assertEqual(result["surface_preservation"]["tabs_restored"], 0, output)
69
+
70
+ def test_unsupported_existing_surface_blocks_before_deploy(self):
71
+ with FakeSf() as fake:
72
+ rc, output = fake.run(
73
+ ["org", "1", "CaseQueue"],
74
+ {"FAKE_EXIST_TABS": json.dumps(["FlexipageType"])},
75
+ )
76
+ deployed_xml = fake.read_state("deployed.xml")
77
+
78
+ self.assertEqual(rc, 1, output)
79
+ self.assertEqual(deployed_xml, "")
80
+ self.assertIn("cannot be safely restored", last_json(output)["blocking_issue"])
81
+
82
+ def test_custom_config_identifier_controls_query_manifest_and_deploy(self):
83
+ custom_config = "Regional_Supervisor"
84
+ with FakeSf() as fake:
85
+ rc, output = fake.run(
86
+ ["org", "1", "CaseQueue", "", "AnySkill", custom_config],
87
+ {
88
+ "FAKE_CONFIG_DN": custom_config,
89
+ "FAKE_MASTER_LABEL": "Regional Supervisor Team",
90
+ },
91
+ )
92
+ deployed_xml = fake.read_state("deployed.xml")
93
+ package_xml = fake.read_state("package.xml")
94
+ trace = fake.read_state("trace")
95
+
96
+ self.assertEqual(rc, 0, output)
97
+ self.assertEqual(last_json(output)["config_developer_name"], custom_config)
98
+ self.assertIn("<members>Regional_Supervisor</members>", package_xml)
99
+ self.assertIn("<masterLabel>Regional Supervisor Team</masterLabel>", deployed_xml)
100
+ self.assertIn("DeveloperName='Regional_Supervisor'", trace)
101
+ self.assertNotIn("DeveloperName='Omni_Supervisor'", trace)
102
+
103
+ def test_invalid_config_identifier_is_rejected_before_org_access(self):
104
+ with FakeSf() as fake:
105
+ rc, output = fake.run(
106
+ ["org", "1", "CaseQueue", "", "AnySkill", "Bad Config' OR Name != '"],
107
+ )
108
+ trace = fake.read_state("trace")
109
+
110
+ self.assertEqual(rc, 1, output)
111
+ self.assertIn("Invalid config_developer_name", output)
112
+ self.assertEqual(trace, "")
113
+
114
+
115
+ if __name__ == "__main__":
116
+ unittest.main(verbosity=2)
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: service-omni-supervisor-permset-assign
3
+ description: "Use to assign the Salesforce-shipped standard ContactCenterSupervisor PermissionSet (default) to N existing supervisor users via PermissionSetAssignment DML. Idempotent — SOQL detects existing (user, perm-set) pairs before POST, and DUPLICATE_VALUE is treated as reused. The standard set carries its own permission-set license and assigns cleanly on Service-Cloud-enabled orgs; a user whose license lacks the entitlement surfaces FIELD_INTEGRITY_EXCEPTION so the operator can fix the profile/license. Triggers: assign the supervisor permset, grant supervisor perms, complete supervisor provisioning. Do not use on production orgs or to assign agent permsets."
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-supervisor-config-deploy"
11
+ accessCheck:
12
+ - type: license
13
+ value: ServiceCloud
14
+ cliTools:
15
+ - tool: ["jq"]
16
+ semver: ">=1.6"
17
+ - tool: ["sf"]
18
+ semver: ">=2.139.6"
19
+ ---
20
+
21
+ # service-omni-supervisor-permset-assign
22
+
23
+ Assign the Salesforce-shipped standard `ContactCenterSupervisor` PermissionSet to existing supervisor users via `PermissionSetAssignment`. The classic Omni-Channel Supervisor UI (Command Center) requires supervisors to hold contact-center supervisor permissions before `service-omni-supervisor-config-deploy` can bind them. The skill uses detect-before-POST idempotency and treats `DUPLICATE_VALUE` as an already-satisfied assignment.
24
+
25
+ **Licensing.** The supervisor system permissions (`IsContactCenterSupervisor`, `OmniSupervisorManageQueue`, `ViewOmnichnlAnlytDshbrd`) are gated by a permission-set license. The standard `ContactCenterSupervisor` set carries its own license linkage and assigns cleanly on a Service-Cloud-enabled org, so it is the default and supported path — a hand-rolled custom set that re-declares these permissions fails with `FIELD_INTEGRITY_EXCEPTION`. If a specific user's license lacks the underlying entitlement, the assignment surfaces that same exception so the operator can move the user to a profile/license that carries it.
26
+
27
+ That custom-permission-set warning does **not** mean assigning the existing Salesforce-shipped `ContactCenterSupervisor` set removes access or rewrites the set. This skill only creates a missing `PermissionSetAssignment`; it never creates, edits, or replaces the permission set itself.
28
+
29
+ ## Inputs
30
+
31
+ ```bash
32
+ bash scripts/verify-and-assign.sh <org-alias> [count=1] [permission-set-names-csv=ContactCenterSupervisor]
33
+ ```
34
+
35
+ - `org-alias` (required).
36
+ - `count` (optional, default `1`, range `1..5`) — must match the supervisor user count.
37
+ - `permission-set-names-csv` (optional, default `ContactCenterSupervisor`) — comma-separated for multiple. Every supervisor gets every listed set (cross-product).
38
+
39
+ ## Preconditions and safety
40
+
41
+ - Target org authenticated via `sf` CLI, Service Cloud license, `sf` CLI ≥ 2.139.6.
42
+ - The supervisor users exist and are active; fewer than `count` active users blocks with a remediation message.
43
+ - The `ContactCenterSupervisor` set is Salesforce-shipped and present on any Service-Cloud-enabled org; a custom name that is missing blocks with a Setup click-path.
44
+ - The executing user has `PermissionsAssignPermissionSets` (standard on System Administrator) — required even for org admins.
45
+ - The three-way `safe_to_write` production guard applies — assigning permission sets on a production org can escalate a real user's privileges, so it blocks with no override.
46
+
47
+ ## Run
48
+
49
+ `verify-and-assign.sh` performs the whole cycle:
50
+
51
+ 1. Compute `safe_to_write`; derive the 8-char org suffix.
52
+ 2. Validate every supplied permission-set name as a well-formed DeveloperName (SOQL-injection guard) before any `sf` call.
53
+ 3. Resolve the `supervisor{1..N}.<suffix>@example.com` users, filtered to `IsActive=true`; block if fewer than `count` are active (an inactive occupant does not satisfy the count).
54
+ 4. Resolve each `PermissionSet` by name; block naming which is missing.
55
+ 5. Query existing `PermissionSetAssignment` for the (user × set) cross-product; compute the missing pairs.
56
+ 6. POST one assignment per missing pair (individual POSTs, no `allOrNone`); treat `DUPLICATE_VALUE` as reused.
57
+ 7. Re-query to confirm final state and emit the report.
58
+
59
+ ## Behavior
60
+
61
+ **Cross-product.** Every supervisor gets every listed set; a partial assignment is a failure, not a feature.
62
+
63
+ **Idempotency.** `PermissionSetAssignment` has a uniqueness constraint on (AssigneeId, PermissionSetId), so a re-POST raises `DUPLICATE_VALUE`; the skill detects existing pairs first and treats that as reused for concurrent-run safety. POSTs are individual so one error never rolls back its siblings, and it re-queries after all POSTs — a 201 only means the write was accepted; a SOQL confirms it is active.
64
+
65
+ **Non-destructive.** Create-only; it never deletes existing assignments (supervisors may hold out-of-band permissions) and derives users from the supervisor pattern rather than an explicit id list.
66
+
67
+ ## Output contract
68
+
69
+ A single JSON object with `status` ∈ `assigned` | `reused` | `partial` | `blocked`, the resolved `permission_sets`, `org_suffix`, `requested_count`, `expected_assignment_count` (= `requested_count × len(permission_sets)`), a `before` snapshot, `assigned_this_run`/`assigned_count`, `reused_count`, an `after` snapshot, `manual_actions`, and `blocking_issue`.
70
+
71
+ - `assigned` — at least one new assignment created; all expected pairs exist after.
72
+ - `reused` — all expected pairs already existed; nothing POSTed.
73
+ - `partial` — some POSTs failed; final count is below expected.
74
+ - `blocked` — precondition failed (production org, missing set, missing/inactive users, or a license that does not allow the permission).
75
+
76
+ `assigned_count + reused_count == expected_assignment_count` unless `partial`; `blocking_issue` is non-null only for `blocked`/`partial`.
77
+
78
+ ## Limitations
79
+
80
+ - Provisioning the user license that the supervisor permset requires is the users-create skill's responsibility, not this one.
81
+ - Assigns individual PermissionSets only — a `PermissionSetGroup` is a different sObject and is out of scope.
82
+ - Create-only; it does not remove assignments.
83
+
84
+ ## References
85
+
86
+ | File | When to read |
87
+ |---|---|
88
+ | `references/api-notes.md` | Before the POST loop — PermissionSetAssignment schema, `DUPLICATE_VALUE` semantics, and why users are derived from the supervisor pattern rather than an explicit id list |
@@ -0,0 +1,48 @@
1
+ # service-omni-supervisor-permset-assign — API notes
2
+
3
+ Load this reference **only when POSTs fail or you need to add new PermissionSets to the skill**. Under normal operation `verify-and-assign.sh` just runs and emits its JSON.
4
+
5
+ ## Why REST POST over Metadata deploy
6
+
7
+ `PermissionSetAssignment` is a **Data API sObject only** — no Metadata API surface. You cannot deploy assignments via `.permissionSetAssignment-meta.xml`. The DML approach with detect-before-POST loops is the only headless option.
8
+
9
+ Contrast with the parent `PermissionSet` itself, which **does** have a Metadata surface (deployable via `.permissionset-meta.xml`). That's why v1.2 has a separate `service-omni-supervisor-permset-metadata-deploy` skill to ship the permset itself; this skill just assigns it.
10
+
11
+ ## Idempotency contract
12
+
13
+ `PermissionSetAssignment` has a Salesforce-enforced uniqueness constraint on `(AssigneeId, PermissionSetId)`. Duplicate POSTs return `DUPLICATE_VALUE` errors.
14
+
15
+ The skill handles this two ways:
16
+
17
+ 1. **Pre-detect via SOQL** — query existing pairs before POSTing; skip already-existing pairs. Avoids most `DUPLICATE_VALUE` responses.
18
+ 2. **Concurrent-run safe** — if another agent (or admin) assigns the same permset between our detect and POST, treat `DUPLICATE_VALUE` as reused (do NOT increment `assigned_count`). No error surfaced.
19
+
20
+ Re-runs on an already-configured org return `status: reused` with `assigned_count: 0` and `before.existing_count == after.assignment_count == expected_assignment_count`.
21
+
22
+ ## Default permset: standard ContactCenterSupervisor (not a custom permset)
23
+
24
+ This skill defaults to the Salesforce-shipped **standard `ContactCenterSupervisor`** PermissionSet, which is present on any Service-Cloud-enabled org and assigns cleanly to a user on a **Salesforce user license** with the **Service Cloud feature** (`UserPermissionsSupportUser=true`).
25
+
26
+ **Why not a custom `Omni_Supervisor` permset?** A custom permset that re-declares the supervisor system permissions (`IsContactCenterSupervisor`, `OmniSupervisorManageQueue`, `ViewOmnichnlAnlytDshbrd`) is rejected with `FIELD_INTEGRITY_EXCEPTION — The user license doesn't allow the permission: IsContactCenterSupervisor`, because those permissions are gated by a permission-set license the custom set does not carry. The standard `ContactCenterSupervisor` permset carries its own license linkage and grants `IsContactCenterSupervisor` cleanly — so it is the only supported path. This skill assigns permsets that already exist on the org; it does not ship or deploy a custom supervisor permset.
27
+
28
+ ## Post-run SOQL verification
29
+
30
+ ```sql
31
+ SELECT AssigneeId, PermissionSetId, Assignee.Username, PermissionSet.Name
32
+ FROM PermissionSetAssignment
33
+ WHERE PermissionSet.Name='ContactCenterSupervisor'
34
+ AND Assignee.Username LIKE 'supervisor%.%'
35
+ ```
36
+
37
+ Expected: N rows, where N = `count` param.
38
+
39
+ ## Common failure modes
40
+
41
+ | Symptom | Cause | Fix |
42
+ |---------|-------|-----|
43
+ | `blocked: Expected PermissionSets [ContactCenterSupervisor]; found []` | Standard permset name not found (unusual — it ships with Service Cloud) | Confirm Service Cloud is enabled on the org |
44
+ | `blocked: Expected N supervisor users ...; found M` | Supervisor users not created or inactive | Provision or reactivate the missing users, then rerun |
45
+ | `DUPLICATE_VALUE` in POST results | Concurrent admin assigned same pair | Treated as reused, no action needed |
46
+ | `FIELD_INTEGRITY_EXCEPTION — The user license doesn't allow the permission: IsContactCenterSupervisor` | Supervisor user is on a license that doesn't carry the contact-center supervisor entitlement | Move the user to a profile/license that carries the entitlement, then rerun |
47
+ | `INSUFFICIENT_ACCESS_OR_READONLY` on POST | SF CLI user lacks ManageUsers perm | Ensure authenticated user is System Administrator |
48
+ | `INSUFFICIENT_ACCESS_OR_READONLY` on POST | SF CLI user lacks ManageUsers perm | Ensure authenticated user is System Administrator |