@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,103 @@
1
+ # Escalation classifier contracts
2
+
3
+ Reference material for the deterministic Node classifiers under `scripts/`. Keeping the
4
+ pass/fail logic in these scripts (not in bash or model prose) satisfies authoring standard
5
+ A9 and makes each verdict unit-testable org-free.
6
+
7
+ ## `classify-agent-active.mjs`
8
+
9
+ Gates the write: escalation can only be wired onto an agent that exists AND whose latest
10
+ `BotVersion` is `Active`.
11
+
12
+ Input is the file path to the JSON stdout of:
13
+
14
+ ```bash
15
+ sf data query -q "SELECT Id,DeveloperName,MasterLabel,
16
+ (SELECT Id,Status FROM BotVersions ORDER BY VersionNumber DESC LIMIT 1)
17
+ FROM BotDefinition WHERE DeveloperName='<developerName>'" --target-org <org> --json
18
+ ```
19
+
20
+ Emits: `{ exists, active, agentId, developerName, latestVersionId, latestVersionStatus, ready, reason }`
21
+ — `ready` is true only when `exists && active`. Exit 0 on a parseable body (verdict is in
22
+ the payload); exit 3 on an unparseable/failed query so the workflow surfaces the raw error
23
+ rather than assuming NOT-READY.
24
+
25
+ ## `extract-outbound-route.mjs`
26
+
27
+ Couples `outboundRouteName` + `outboundRouteType` from WITHIN the same
28
+ `outboundRouteConfigs` block so a bundle cannot pass by carrying an unrelated name and type
29
+ in different blocks. The compiled `GenAiPlannerBundle` nests the route in a planner surface:
30
+
31
+ ```xml
32
+ <plannerSurfaces>
33
+ <surfaceType>Messaging</surfaceType> <!-- or CustomerWebClient for MIAW -->
34
+ <outboundRouteConfigs>
35
+ <escalationMessage>…</escalationMessage>
36
+ <outboundRouteName>Human_Escalation_Outbound_Flow</outboundRouteName>
37
+ <outboundRouteType>OmniChannelFlow</outboundRouteType>
38
+ </outboundRouteConfigs>
39
+ </plannerSurfaces>
40
+ ```
41
+
42
+ Emits `{ name, type, surface, sameBlock, messagingSurface }` for the block matched by the
43
+ expected flow name (or the first block if none matches). `sameBlock=true` means name+type
44
+ came from the same block; `messagingSurface=true` means it sits on a Messaging-class
45
+ surface. Exit 0 on any parseable input (missing file => empty result); exit 2 on bad usage.
46
+
47
+ ## `patch-escalation-surfaces.mjs`
48
+
49
+ Schema-aware, loss-less, idempotent in-place patcher for the two doc-driven surfaces. It
50
+ only ever touches the two target elements, never reorders surrounding metadata, and
51
+ refuses (exit 4) rather than guess when no safe insertion point exists.
52
+
53
+ **XSD order (authoritative — `GenAiPlannerBundle.json` wsdl_segment):**
54
+
55
+ - `AiPlannerSurfaceDef` (`<plannerSurfaces>`): `adaptiveResponseAllowed?`,
56
+ `callRecordingAllowed?`, `outboundRouteConfigs*`, `surface`, `surfaceType` — a NEW
57
+ `<outboundRouteConfigs>` MUST be inserted BEFORE `<surface>` (never appended after it).
58
+ - `AiPlannerSurfOtbdRouteDef` (`<outboundRouteConfigs>`): `escalationMessage?`,
59
+ `outboundRouteName`, `outboundRouteType`.
60
+ - `GenAiPlugin` / `GenAiLocalPlugin`: `aiPluginUtterances*`, `canEscalate?`,
61
+ `description?`, `developerName`, … — `<canEscalate>` MUST be inserted AFTER the last
62
+ `<aiPluginUtterances>` and BEFORE `<description>` (or, if absent, before the first
63
+ following required sibling — `developerName`/`masterLabel`/…).
64
+
65
+ Modes:
66
+
67
+ ```bash
68
+ node patch-escalation-surfaces.mjs canEscalate <genAiPlugin-xml-file>
69
+ node patch-escalation-surfaces.mjs outboundRoute <genAiPlannerBundle-xml-file> <flowApiName> [escalationMessage]
70
+ ```
71
+
72
+ Patched IN PLACE. Exit 0 on success (prints a short JSON summary), 2 on bad usage, 4 when
73
+ no safe patch point is found (nothing written).
74
+
75
+ ## `verify-escalation-config.mjs`
76
+
77
+ Renders the single deterministic verdict from an evidence object assembled by
78
+ `verify-and-configure.sh` (retrieved XML greps + SOQL reads).
79
+
80
+ `evidence.json` shape (all keys optional; missing => treated as not-satisfied):
81
+
82
+ | key | meaning |
83
+ | --- | --- |
84
+ | `canEscalate` | escalation topic flag set |
85
+ | `outboundRouteName` | route name on the bundle |
86
+ | `outboundRouteType` | must equal `OmniChannelFlow` |
87
+ | `outboundRouteSameBlock` | name+type from the SAME config block |
88
+ | `outboundRouteMessagingSurface` | block sits on a Messaging planner surface |
89
+ | `expectedFlowName` | expected outbound flow name |
90
+ | `flowActiveVersionId` | non-empty => flow active |
91
+ | `queueId` | non-empty => queue exists |
92
+ | `queueSobjectPresent` | context object bound to the queue |
93
+ | `queueHasActiveDirectUserMember` | ≥1 active DIRECT User member (necessary, not sufficient — Omni perm + presence access are proven only at runtime) |
94
+ | `queueRoutingConfigPresent` | QRC exists |
95
+ | `queueRoutingConfigBound` | `Group.QueueRoutingConfigId` points at the QRC |
96
+ | `agentActive` | latest BotVersion active |
97
+ | `thresholdAuthored` | directive policy authored (not a counter) |
98
+ | `defaultFailureThreshold` | numeric consecutive-failure threshold rendered into the directive (evidence only, never a gate) |
99
+
100
+ Emits `{ verdict, deterministicPass, directivePass, checks[], missing[] }` where `verdict`
101
+ is `CONFIGURED` | `INCOMPLETE`. The deterministic surfaces gate `CONFIGURED`; the threshold
102
+ directive is reported separately (never blocks the headless verdict — it is eval-verified,
103
+ not metadata-verified). Exit 0 on a parseable body; exit 3 on unparseable input.
@@ -0,0 +1,63 @@
1
+ # Escalation mechanism reference
2
+
3
+ Agent → human escalation in Agentforce is assembled from three declarative surfaces plus
4
+ one instruction surface. Only the first three are deterministically writable and verifiable
5
+ via the Metadata/Data API; the fourth (threshold policy) is directive text verified by
6
+ eval, and the actual conversational trigger is manual/runtime.
7
+
8
+ ## 1. `canEscalate` on the escalation topic (`GenAiPlugin`)
9
+
10
+ The agent topic that represents "hand off to a human" must have `<canEscalate>true</canEscalate>`.
11
+ Retrieve the topic, set the flag, redeploy.
12
+
13
+ ```bash
14
+ sf project retrieve start --target-org "$ORG" \
15
+ --metadata "GenAiPlugin:${ESCALATION_TOPIC_API_NAME}" --target-metadata-dir /tmp/esc
16
+ # edit <canEscalate>true</canEscalate> in the retrieved -meta.xml
17
+ sf project deploy start --target-org "$ORG" --metadata "GenAiPlugin:${ESCALATION_TOPIC_API_NAME}"
18
+ ```
19
+
20
+ Verify (the retrieved XML must contain `<canEscalate>true</canEscalate>`). There is no
21
+ SOQL object for `canEscalate`; the source of truth is the retrieved metadata.
22
+
23
+ ## 2. `outboundRouteConfigs` on the agent's Messaging planner surface (`GenAiPlannerBundle`)
24
+
25
+ The `GenAiPlannerBundle` for the agent carries the Messaging surface. Its
26
+ `outboundRouteConfigs` block wires the escalation to an Omni-Channel outbound flow:
27
+
28
+ ```xml
29
+ <outboundRouteConfigs>
30
+ <escalationMessage>Transferring you to a live support agent.</escalationMessage>
31
+ <outboundRouteName>Human_Escalation_Outbound_Flow</outboundRouteName>
32
+ <outboundRouteType>OmniChannelFlow</outboundRouteType>
33
+ </outboundRouteConfigs>
34
+ ```
35
+
36
+ Retrieve the bundle, add/update the block on the Messaging surface, redeploy. `outboundRouteName`
37
+ must equal the active outbound `RoutingFlow` API name (see #3).
38
+
39
+ ## 3. Outbound QueueBased `RoutingFlow`
40
+
41
+ The bundled asset `assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml`
42
+ is a QueueBased outbound flow template that routes the escalated conversation to the human
43
+ queue. It looks the queue up by `DeveloperName` at runtime (no hardcoded Id), so it is
44
+ portable across orgs. Tokens `__FLOW_DEVELOPER_NAME__`, `__FLOW_LABEL__`,
45
+ `__QUEUE_DEVELOPER_NAME__`, `__SERVICE_CHANNEL_DEV_NAME__`, `__SERVICE_CHANNEL_LABEL__`
46
+ are substituted before deploy.
47
+
48
+ After deploy, `FlowDefinitionView.ActiveVersionId` for the flow must be non-null.
49
+
50
+ ## 4. Human queue
51
+
52
+ The escalation target is a queue whose `QueueSobject` includes the routed context object
53
+ (`MessagingSession` by default, for Enhanced Chat / MIAW), plus a `QueueRoutingConfig`. See
54
+ [queue-resolution.md](../../service-agentforce-channel-configure/references/queue-resolution.md)
55
+ for the create-or-adopt recipe. Provision any broader routing infrastructure through an
56
+ approved Omni setup workflow before running this skill.
57
+
58
+ ## Handoff to `service-agentforce-channel-configure`
59
+
60
+ Inbound transport (`sessionHandlerAsa` on the MessagingChannel, Branch A) and the outbound
61
+ `connection customer_web_client:` connection block on the agent are owned by
62
+ `service-agentforce-channel-configure`. This skill focuses on the escalation-specific
63
+ surfaces (#1, #2, #3, #4) and the threshold policy, delegating transport wiring to that skill.
@@ -0,0 +1,44 @@
1
+ # Failure-threshold policy (native, directive-based)
2
+
3
+ ## Why this is not a metadata counter
4
+
5
+ Agentforce does not expose a metadata field or setting that counts "consecutive failed
6
+ turns" and escalates automatically. The "escalate after two failures" behaviour is a
7
+ **planner policy expressed as instruction text** in the agent's Agent Script (NGA
8
+ authoring model). This is the platform-native representation the user selected.
9
+
10
+ Consequences:
11
+
12
+ - The threshold is **authored, not enforced by a counter**. The bundled template
13
+ [`assets/escalation-thresholds.instructions.md`](../assets/escalation-thresholds.instructions.md)
14
+ is the source directive text.
15
+ - It is **verified by an ADK eval rubric** (does the agent escalate on the 2nd failure? on
16
+ the 1st failure for password reset?) and a **documented manual conversation test** — never
17
+ by a deterministic metadata round-trip.
18
+ - The `verify-and-configure.sh` verdict therefore reports the threshold as `directive`
19
+ (authored / not-authored), distinct from the `deterministic` config surfaces
20
+ (`canEscalate`, `outboundRouteConfigs` name+type coupling on the Messaging surface, outbound
21
+ flow Active, queue + QueueSobject + bound QueueRoutingConfig, ≥1 active human member, agent Active).
22
+
23
+ ## Recommended thresholds
24
+
25
+ The threshold is a **caller input**, not a fixed constant. The values below are defaults;
26
+ a scenario that mandates a different number (e.g. a narrative requiring escalation after
27
+ **three** consecutive failures) supplies its own value via the skill input — no code change
28
+ is needed.
29
+
30
+ | Scenario | Threshold | Rationale |
31
+ |---|---|---|
32
+ | Default (any unresolved request) | 2 consecutive failures | Give the agent one retry before handing off |
33
+ | Password reset / credential issues | 1 failure | Time-sensitive; do not retry repeatedly |
34
+ | Caller-specified | any N | Whatever the scenario's authoritative requirement is (pass N as the input) |
35
+
36
+ ## Authoring steps
37
+
38
+ 1. Substitute tokens in the template (`__DEFAULT_FAILURES__=2`, `__RESET_TOPIC_LABEL__`,
39
+ `__ESCALATION_MESSAGE__`).
40
+ 2. Add the default directive to the agent's global/system instructions.
41
+ 3. Add the per-topic override to the password-reset topic instructions.
42
+ 4. Republish + reactivate the agent (`sf agent validate|publish|activate ... --target-org $ORG`).
43
+ 5. Confirm via the eval rubric and the manual test in
44
+ [runtime-verification.md](./runtime-verification.md).
@@ -0,0 +1,57 @@
1
+ # Next-gen (NGA) escalation — detection, surface split, and verdict
2
+
3
+ The classic escalation surface (`GenAiPlannerBundle.outboundRouteConfigs` + `GenAiPlugin.canEscalate`) does not exist on next-gen authoring (NGA) orgs. NGA agents are defined by `AiAuthoringBundle` (Agent Script), and the escalation surface moves into the bundle. This skill supports both models from one code path; only the agent-side surface differs.
4
+
5
+ ## Detection (Phase 1b)
6
+
7
+ `sf org list metadata-types` identifies the model surfaces available in the org. When both surfaces exist, the skill retrieves the requested agent from each surface and classifies that specific target rather than applying an org-wide default:
8
+
9
+ | Metadata types exposed | `authoring_model` | Agent surface authored/verified |
10
+ |---|---|---|
11
+ | Requested agent is found only in `GenAiPlannerBundle` | `classic` | `canEscalate` + `outboundRouteConfigs` |
12
+ | Requested agent is found only in `AiAuthoringBundle` | `nga` | `@utils.escalate` (Service) / create-record (Employee) |
13
+ | Requested agent is found in both surfaces | `ambiguous` | — (skill blocks before any write) |
14
+ | Requested agent is found in neither surface while both models exist | `none` | — (skill blocks before any write) |
15
+
16
+ `AUTHORING_MODEL_OVERRIDE=classic|nga` explicitly pins the branch when the target is genuinely ambiguous or metadata retrieval is inconclusive. There is no classic-first default: an NGA target in a mixed-model org stays NGA.
17
+
18
+ ## Why classic ≠ NGA (not a straight port)
19
+
20
+ The classic skill's value was deterministically authoring + verifying a failure-threshold outbound route on one metadata surface. NGA splits that into pieces of different natures:
21
+
22
+ | Classic single surface | NGA equivalent | Deterministic? |
23
+ |---|---|---|
24
+ | `outboundRouteConfigs` → named queue | channel → queue Omni routing (the routing half this skill builds) | yes |
25
+ | failure-threshold trigger | Agent Script instruction / `@utils.escalate` action | no — prompt-led (a directive) |
26
+ | (n/a for employee agents) | Employee agent → create Incident/Case action → Omni-route that record | yes |
27
+
28
+ There is no numeric "escalate after N failures" field in Agent Script; the threshold stays a directive (the same boundary the classic path already uses).
29
+
30
+ ## Service vs Employee split
31
+
32
+ - **Service agent** — declares `connection messaging:` and can call `@utils.escalate` for a live hand-off routed through the messaging connection to the queue.
33
+ - **Employee agent** — cannot declare `connection messaging:` or use `@utils.escalate`. Its escalation surrogate is an action that creates a routable record (Case/Incident/ticket) which then Omni-routes to the human queue.
34
+
35
+ `scripts/classify-nga-escalation.mjs` walks the retrieved `AiAuthoringBundle` (in-process, so it never invokes `find` — the sandbox blocks `find -exec`'s `ARG_MAX` probe) and returns:
36
+
37
+ To avoid a false `CONFIGURED`, it scans **only Agent Script** (`*.agent` files, or any file whose content declares `start_agent`), **strips comments** (`/* */`, whole-line `//`/`#`), and proves reachability **per agent block**: the escalation surface must live in the same `start_agent` block as its trigger, under a `reasoning: actions:` section (a line more indented than the `actions:` header). A commented-out block, prose mention, cross-block match, or unrelated file no longer satisfies the surface — when reachability cannot be proven it reports `escalationSurfacePresent:false` (→ caller stays `INCOMPLETE`). An unreadable/missing retrieve dir exits `3` (inconclusive), never an empty exit `0`.
38
+
39
+ ```text
40
+ { agentType, bundleFound, connectionMessaging, escalateActionPresent, createRecordActionPresent, escalationSurfacePresent }
41
+ ```
42
+
43
+ - `agentType`: `service` if `connection messaging:` present, else `employee` (or `unknown` when no bundle was retrieved).
44
+ - `escalationSurfacePresent`: `escalateActionPresent` for Service, `createRecordActionPresent` for Employee. `createRecordActionPresent` is a heuristic (action refs matching create + case/incident/ticket/record) — treat a false negative as "author via agentforce-generate", never as a hard failure of the agent.
45
+
46
+ ## NGA verdict set
47
+
48
+ `verify-escalation-config.mjs` keeps the model-agnostic routing checks (`outboundFlowActive`, `humanQueue`, `queueSobject`, `queueHasActiveDirectUserMember`, `queueRoutingConfig`, `queueRoutingConfigBound`, `agentActive`) and swaps the surface checks:
49
+
50
+ - classic → `canEscalate` + `outboundRouteConfigs`
51
+ - nga → `ngaEscalationSurface` (from `escalationSurfacePresent`)
52
+
53
+ `thresholdDirective` remains a directive check in both. `CONFIGURED` requires all deterministic checks; the threshold is reported separately.
54
+
55
+ ## Authoring delegation
56
+
57
+ This skill **verifies** the NGA surface; it does not mutate Agent Script. When `ngaEscalationSurface` is missing the verdict is `INCOMPLETE` and `next_steps` points to `agentforce-generate` to author the surface: for a Service agent add a reachable `{!@utils.escalate}` action (needs `connection messaging:`); for an Employee agent add a create-record (Case/Incident) action that Omni-routes to the queue. Re-run afterward to reach `CONFIGURED`.
@@ -0,0 +1,72 @@
1
+ # Runtime & manual verification checklist
2
+
3
+ The deterministic config surfaces are verified headlessly by `verify-and-configure.sh`
4
+ (see the JSON verdict). The conversational behaviour and context preservation **cannot be
5
+ driven headlessly** and must be confirmed with a live conversation (per the EC V2 reference).
6
+
7
+ ## A. Deterministic config verdict (headless — done by the skill)
8
+
9
+ `verify-and-configure.sh` round-trips and asserts:
10
+
11
+ - `canEscalate=true` on the escalation topic (`GenAiPlugin`).
12
+ - `outboundRouteConfigs` on the `GenAiPlannerBundle` Messaging planner surface couples
13
+ `outboundRouteName` (= the outbound flow API name) to `outboundRouteType=OmniChannelFlow`
14
+ in the SAME block on a Messaging-class surface.
15
+ - Outbound `RoutingFlow` `ActiveVersionId` is non-null (`FlowDefinitionView`).
16
+ - The human queue exists with a `QueueSobject` for the context object (`MessagingSession`
17
+ by default), a `QueueRoutingConfig` bound to the queue (`Group.QueueRoutingConfigId`), and
18
+ **at least one active human member** (`GroupMember` resolving to an active `User`).
19
+ - The agent's latest `BotVersion` is `Active` after republish.
20
+
21
+ ## B. Threshold policy (eval rubric — not a counter)
22
+
23
+ - ADK eval `TwoFailureThreshold`: on the 2nd consecutive failed attempt the agent escalates.
24
+ - ADK eval `PasswordResetOverride`: on the 1st failed password-reset attempt the agent escalates.
25
+
26
+ ## C. Manual conversation test (runtime only)
27
+
28
+ 1. Open the Enhanced Chat / MIAW deployment as an end user.
29
+ 2. Ask the agent something it can resolve — confirm no premature escalation.
30
+ 3. Trigger two consecutive failed attempts on the same request — confirm the agent emits
31
+ the escalation message and hands off.
32
+ 4. Confirm an `AgentWork` record is created against the human queue:
33
+
34
+ ```bash
35
+ sf data query --target-org "$ORG" --json \
36
+ --query "SELECT Id, Status, ServiceChannel, WorkItemId FROM AgentWork ORDER BY CreatedDate DESC LIMIT 5"
37
+ ```
38
+
39
+ 5. Confirm **context preservation**: the human agent receives the same `MessagingSession`
40
+ with the full prior transcript (same `MessagingSession.Id`, not a new session).
41
+
42
+ ```bash
43
+ sf data query --target-org "$ORG" --json \
44
+ --query "SELECT Id, Status, Origin FROM MessagingSession ORDER BY LastModifiedDate DESC LIMIT 5"
45
+ ```
46
+
47
+ Context preservation and `AgentWork` creation are runtime facts — record the result in the
48
+ run notes; they are not part of the headless verdict.
49
+
50
+ ## D. Real-org proof record — 2026-08-17 (`sdb38` trial CDO)
51
+
52
+ Read-only §7 verification run against a non-production org (`IsSandbox=false`,
53
+ `TrialExpirationDate` non-null ⇒ `safe_to_write=true`). IDs abbreviated.
54
+
55
+ | Check | Result |
56
+ | --- | --- |
57
+ | Org safety | PASS — Enterprise trial CDO, non-production |
58
+ | Human queue + QRC bind | PASS — `General_IT_Queue`, `QueueRoutingConfigId=0K9…00BA` |
59
+ | `QueueSobject` context object | PASS — `MessagingSession` |
60
+ | Active human members | PASS — 2 active users |
61
+ | Outbound `RoutingFlow` active | PASS — `ActiveVersionId=301…pYBB` |
62
+ | Active MessagingChannels | PASS — 4 active |
63
+ | Queue-based routing runtime | PASS — `PendingServiceRouting` rows `IsReadyForRouting=true`, `RoutingType=QueueBased`; `AgentWork` rows `Closed`/`Declined` on `sfdc_livemessage`; `MessagingSession` rows `Ended`/`Waiting` |
64
+
65
+ **Not proven headlessly (manual step required):**
66
+
67
+ - Agent-authoring side (`canEscalate` + `outboundRouteConfigs` on a live Agentforce planner
68
+ bundle) — the default agent developer name was absent on this org; running the authoring
69
+ path requires an explicit `AGENT_DEVELOPER_NAME` (e.g. an Active `ExternalCopilot` agent).
70
+ - Phase 4 conversational escalation — must be driven through a live Enhanced Messaging
71
+ conversation (section C). Queue-based routing→agent-accept is already demonstrated above,
72
+ but the agent→human handoff trigger itself is a manual runtime confirmation.
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ // Precondition classifier: BotDefinition+latest BotVersion query JSON → { exists, active, ready, ... }; ready only when exists && active; exit 3 on unparseable. Query/output shape: references/classifier-contracts.md.
3
+
4
+ import { readFileSync } from 'node:fs';
5
+
6
+ const [queryPath, developerName] = process.argv.slice(2);
7
+ if (!queryPath || !developerName) {
8
+ process.stderr.write('usage: node classify-agent-active.mjs <bot-query.json> <developerName>\n');
9
+ process.exit(2);
10
+ }
11
+
12
+ let data;
13
+ try {
14
+ const text = readFileSync(queryPath, 'utf8').trim();
15
+ data = text ? JSON.parse(text) : null;
16
+ } catch {
17
+ process.stderr.write(`error: could not read/parse ${queryPath}\n`);
18
+ process.exit(3);
19
+ }
20
+
21
+ if (!data || (typeof data.status === 'number' && data.status !== 0) || data.result === undefined) {
22
+ process.stderr.write('error: query did not return a results envelope; surface the raw CLI error and stop\n');
23
+ process.exit(3);
24
+ }
25
+
26
+ const records = Array.isArray(data.result?.records) ? data.result.records : [];
27
+ const wantedLower = String(developerName).toLowerCase();
28
+ const matches = records.filter((r) => String(r?.DeveloperName ?? '').toLowerCase() === wantedLower);
29
+ const exists = matches.length > 0;
30
+
31
+ const latestVersion = exists ? matches[0]?.BotVersions?.records?.[0] ?? null : null;
32
+ const latestVersionStatus = latestVersion?.Status ?? null;
33
+ const active = exists && latestVersionStatus === 'Active';
34
+
35
+ let reason;
36
+ if (!exists) reason = 'agent-not-found';
37
+ else if (!active) reason = 'agent-inactive';
38
+ else reason = 'ready';
39
+
40
+ process.stdout.write(JSON.stringify({
41
+ exists,
42
+ active,
43
+ agentId: exists ? (matches[0].Id ?? null) : null,
44
+ developerName,
45
+ latestVersionId: latestVersion?.Id ?? null,
46
+ latestVersionStatus,
47
+ ready: exists && active,
48
+ reason,
49
+ }, null, 2) + '\n');
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ // Classify the escalation surface of a retrieved next-gen (AiAuthoringBundle) agent -> { agentType, connectionMessaging, escalateActionPresent, createRecordActionPresent, escalationSurfacePresent, bundleFound }. Detection rules + Service-vs-Employee rationale: references/nga-escalation.md. Exit 3 on an unreadable dir.
3
+ //
4
+ // Hardening (avoids false CONFIGURED): only actual Agent Script (.agent files, or any file whose
5
+ // content declares `start_agent`) is scanned; comments are stripped; and the escalation surface must
6
+ // live in the SAME agent block as its trigger, under a `reasoning: actions:` section - a comment,
7
+ // example, or unrelated file can no longer satisfy the match. When reachability cannot be proven the
8
+ // surface is reported absent (escalationSurfacePresent:false) so the caller stays INCOMPLETE.
9
+
10
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+
13
+ const [retrieveDir] = process.argv.slice(2);
14
+ if (!retrieveDir) {
15
+ process.stderr.write('usage: node classify-nga-escalation.mjs <retrieve-dir>\n');
16
+ process.exit(2);
17
+ }
18
+
19
+ // The TOP dir must be readable — an unreadable/missing retrieve dir is inconclusive, not "no surface"
20
+ // (file contract: exit 3). Nested unreadable files are skipped below (a single bad file is not fatal).
21
+ try {
22
+ if (!statSync(retrieveDir).isDirectory()) throw new Error('not a directory');
23
+ readdirSync(retrieveDir);
24
+ } catch {
25
+ process.stderr.write(`error: could not read ${retrieveDir}\n`);
26
+ process.exit(3);
27
+ }
28
+
29
+ // Strip comments so a commented-out / example escalation block cannot satisfy the regex: remove
30
+ // /* ... */ blocks, then drop whole-line // and # comments (leaves inline // inside strings alone).
31
+ function stripComments(text) {
32
+ const noBlock = text.replace(/\/\*[\s\S]*?\*\//g, '');
33
+ return noBlock
34
+ .split('\n')
35
+ .map((line) => {
36
+ const t = line.trimStart();
37
+ return t.startsWith('//') || t.startsWith('#') ? '' : line;
38
+ })
39
+ .join('\n');
40
+ }
41
+
42
+ // Walk the retrieve dir in-process (no `find`; the sandbox blocks find -exec's ARG_MAX probe) and
43
+ // collect ONLY Agent Script: files named *.agent, or any file whose content declares `start_agent`
44
+ // (covers a differently-named script). bundleFound also counts *.bundle-meta.xml so a bundle with no
45
+ // readable script still reports bundleFound:true (→ agentType resolvable, surface simply absent).
46
+ function collect(dir, acc) {
47
+ let entries;
48
+ try {
49
+ entries = readdirSync(dir);
50
+ } catch {
51
+ return acc;
52
+ }
53
+ for (const name of entries) {
54
+ const full = join(dir, name);
55
+ let st;
56
+ try {
57
+ st = statSync(full);
58
+ } catch {
59
+ continue;
60
+ }
61
+ if (st.isDirectory()) {
62
+ collect(full, acc);
63
+ continue;
64
+ }
65
+ if (!st.isFile()) continue;
66
+ const isAgentExt = /\.agent$/i.test(name);
67
+ if (isAgentExt || /\.bundle-meta\.xml$/i.test(name)) acc.bundleFound = true;
68
+ let raw;
69
+ try {
70
+ raw = readFileSync(full, 'utf8');
71
+ } catch {
72
+ continue; // skip unreadable/binary file
73
+ }
74
+ if (isAgentExt || /^[ \t]*start_agent\b/im.test(raw)) {
75
+ acc.scripts.push(stripComments(raw));
76
+ }
77
+ }
78
+ return acc;
79
+ }
80
+
81
+ const scanned = collect(retrieveDir, { scripts: [], bundleFound: false });
82
+
83
+ // Split concatenated Agent Script into per-agent blocks. Each `start_agent <name>:` opens a block that
84
+ // runs until the next start_agent (or EOF). Reachability is proven per block, not across the file.
85
+ function splitAgentBlocks(scriptText) {
86
+ const blocks = [];
87
+ let cur = null;
88
+ for (const line of scriptText.split('\n')) {
89
+ if (/^\s*start_agent\b/i.test(line)) {
90
+ if (cur) blocks.push(cur);
91
+ cur = [line];
92
+ } else if (cur) {
93
+ cur.push(line);
94
+ }
95
+ }
96
+ if (cur) blocks.push(cur);
97
+ return blocks;
98
+ }
99
+
100
+ // True when `re` matches an action line inside a `reasoning: actions:` section of the block — i.e. the
101
+ // match is more indented than the `actions:` header it lives under (a real action, not prose/an example).
102
+ function actionMatches(blockLines, re) {
103
+ let actionsIndent = -1;
104
+ for (const line of blockLines) {
105
+ if (line.trim() === '') continue;
106
+ const indent = line.length - line.trimStart().length;
107
+ if (actionsIndent >= 0) {
108
+ if (indent > actionsIndent) {
109
+ if (re.test(line)) return true;
110
+ continue;
111
+ }
112
+ actionsIndent = -1; // dedented out of the actions section; re-check this line as a new header
113
+ }
114
+ if (/^actions\s*:/.test(line.trim())) actionsIndent = indent;
115
+ }
116
+ return false;
117
+ }
118
+
119
+ const CREATE_RECORD_RE =
120
+ /@actions\.[A-Za-z0-9_]*create[A-Za-z0-9_]*(case|incident|ticket|record)|create[_-]?(case|incident|ticket)\b/i;
121
+ const ESCALATE_RE = /@utils\.escalate\b/i;
122
+ const MESSAGING_RE = /^\s*connection\s+messaging\s*:/im;
123
+
124
+ let connectionMessaging = false;
125
+ let escalateActionPresent = false;
126
+ let createRecordActionPresent = false;
127
+ let serviceSurface = false; // messaging + reachable @utils.escalate in the SAME block
128
+ let employeeSurface = false; // no messaging + reachable create-record action in the block
129
+
130
+ for (const script of scanned.scripts) {
131
+ for (const block of splitAgentBlocks(script)) {
132
+ const text = block.join('\n');
133
+ const hasMessaging = MESSAGING_RE.test(text);
134
+ const hasEscalate = actionMatches(block, ESCALATE_RE);
135
+ const hasCreateRecord = actionMatches(block, CREATE_RECORD_RE);
136
+ connectionMessaging = connectionMessaging || hasMessaging;
137
+ escalateActionPresent = escalateActionPresent || hasEscalate;
138
+ createRecordActionPresent = createRecordActionPresent || hasCreateRecord;
139
+ if (hasMessaging && hasEscalate) serviceSurface = true;
140
+ if (!hasMessaging && hasCreateRecord) employeeSurface = true;
141
+ }
142
+ }
143
+
144
+ // Service agents escalate via @utils.escalate; Employee agents lack messaging and must create a
145
+ // routable record instead. Without a retrieved bundle the type is unknown.
146
+ let agentType = 'unknown';
147
+ if (scanned.bundleFound) agentType = connectionMessaging ? 'service' : 'employee';
148
+
149
+ let escalationSurfacePresent = false;
150
+ if (agentType === 'service') escalationSurfacePresent = serviceSurface;
151
+ else if (agentType === 'employee') escalationSurfacePresent = employeeSurface;
152
+
153
+ process.stdout.write(
154
+ JSON.stringify(
155
+ {
156
+ agentType,
157
+ bundleFound: scanned.bundleFound,
158
+ connectionMessaging,
159
+ escalateActionPresent,
160
+ createRecordActionPresent,
161
+ escalationSurfacePresent,
162
+ },
163
+ null,
164
+ 2,
165
+ ) + '\n',
166
+ );
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ // Extracts outbound-route wiring from a retrieved GenAiPlannerBundle, coupling routeName+routeType within one outboundRouteConfigs block → { name, type, surface, sameBlock, messagingSurface }; exit 2 on bad usage. Details: references/classifier-contracts.md.
3
+
4
+ import { readFileSync } from 'node:fs';
5
+
6
+ const [xmlPath, expectedFlow = ''] = process.argv.slice(2);
7
+ if (!xmlPath) {
8
+ process.stderr.write('usage: node extract-outbound-route.mjs <bundle-xml-file> <expected-flow-name>\n');
9
+ process.exit(2);
10
+ }
11
+
12
+ const empty = { name: '', type: '', surface: '', sameBlock: false, messagingSurface: false };
13
+
14
+ let xml = '';
15
+ try {
16
+ xml = readFileSync(xmlPath, 'utf8');
17
+ } catch {
18
+ process.stdout.write(JSON.stringify(empty) + '\n');
19
+ process.exit(0);
20
+ }
21
+
22
+ const MESSAGING_SURFACES = new Set(['Messaging', 'CustomerWebClient']);
23
+ const tag = (block, name) => {
24
+ const m = block.match(new RegExp(`<${name}>\\s*([^<]*?)\\s*</${name}>`, 's'));
25
+ return m ? m[1].trim() : '';
26
+ };
27
+
28
+ // Collect candidate blocks: prefer plannerSurfaces entries (so we know the surfaceType), and
29
+ // fall back to bare outboundRouteConfigs blocks if the bundle is flat/uncompiled.
30
+ const candidates = [];
31
+ for (const sm of xml.matchAll(/<plannerSurfaces>([\s\S]*?)<\/plannerSurfaces>/g)) {
32
+ const surfaceBlock = sm[1];
33
+ const surface = tag(surfaceBlock, 'surfaceType');
34
+ for (const cm of surfaceBlock.matchAll(/<outboundRouteConfigs>([\s\S]*?)<\/outboundRouteConfigs>/g)) {
35
+ candidates.push({ surface, block: cm[1] });
36
+ }
37
+ }
38
+ if (candidates.length === 0) {
39
+ for (const cm of xml.matchAll(/<outboundRouteConfigs>([\s\S]*?)<\/outboundRouteConfigs>/g)) {
40
+ candidates.push({ surface: '', block: cm[1] });
41
+ }
42
+ }
43
+
44
+ const describe = (c) => {
45
+ const name = tag(c.block, 'outboundRouteName');
46
+ const type = tag(c.block, 'outboundRouteType');
47
+ return {
48
+ name,
49
+ type,
50
+ surface: c.surface,
51
+ sameBlock: name !== '' && type !== '',
52
+ messagingSurface: MESSAGING_SURFACES.has(c.surface),
53
+ };
54
+ };
55
+
56
+ let chosen = null;
57
+ if (expectedFlow) {
58
+ chosen = candidates.map(describe).find((d) => d.name === expectedFlow) || null;
59
+ }
60
+ if (!chosen) {
61
+ chosen = candidates.length ? describe(candidates[0]) : null;
62
+ }
63
+ if (!chosen) {
64
+ chosen = empty;
65
+ }
66
+
67
+ process.stdout.write(JSON.stringify(chosen) + '\n');