@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.
- package/package.json +1 -1
- package/skills/agentforce-observe/SKILL.md +32 -4
- package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
- package/skills/dx-devops-project-manage/SKILL.md +197 -0
- package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
- package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
- package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
- package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
- package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
- package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
- package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
- package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
- package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
- package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
- package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
- package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
- package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
- package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
- package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
- package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
- package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
- package/skills/education-cloud-domain-configure/SKILL.md +234 -0
- package/skills/education-cloud-domain-configure/references/dependent-features.md +198 -0
- package/skills/education-cloud-domain-configure/references/domain-features/academic-operations.md +386 -0
- package/skills/education-cloud-domain-configure/references/domain-features/alumni-relations.md +155 -0
- package/skills/education-cloud-domain-configure/references/domain-features/cross-domain-dependencies.md +18 -0
- package/skills/education-cloud-domain-configure/references/domain-features/industriessettings-toggle-reference.md +43 -0
- package/skills/education-cloud-domain-configure/references/domain-features/mentoring.md +198 -0
- package/skills/education-cloud-domain-configure/references/domain-features/recruitment-admissions.md +315 -0
- package/skills/education-cloud-domain-configure/references/domain-features/student-management.md +155 -0
- package/skills/education-cloud-domain-configure/references/domain-features/student-success.md +249 -0
- package/skills/education-cloud-domain-configure/references/domain-features.md +27 -0
- package/skills/education-cloud-domain-configure/references/gotchas-extended.md +23 -0
- package/skills/education-cloud-domain-configure/references/toggle-write-path.md +67 -0
- package/skills/education-cloud-domain-configure/scripts/check_license_provisioned.py +62 -0
- package/skills/education-cloud-domain-configure/scripts/check_org_edition.py +44 -0
- package/skills/education-cloud-domain-configure/scripts/check_permission_assigned.py +39 -0
- package/skills/education-cloud-multi-campus-configure/SKILL.md +7 -0
- package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +1 -2
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
- package/skills/experience-cms-brand-apply/SKILL.md +5 -5
- package/skills/experience-cms-brand-create/SKILL.md +2 -2
- package/skills/experience-cms-content-generate/SKILL.md +1 -0
- package/skills/experience-cms-content-render/SKILL.md +173 -0
- package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
- package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
- package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
- package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
- package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
- package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
- package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
- package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
- package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
- package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
- package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
- package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
- package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
- package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
- package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
- package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
- package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
- package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
- package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
- package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
- package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
- package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
- package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
- package/skills/experience-cms-content-render/references/package-api.md +106 -0
- package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
- package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
- package/skills/experience-cms-content-render/references/verify.md +49 -0
- package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
- package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
- package/skills/experience-search-coordinate/SKILL.md +198 -0
- package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
- package/skills/experience-search-coordinate/references/content-route.md +313 -0
- package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
- package/skills/experience-search-coordinate/references/media-route.md +172 -0
- package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
- package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
- package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
- package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
- package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
- package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
- package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
- package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
- package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
- package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
- package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
- package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
- package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
- package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
- package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
- package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
- package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
- package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
- package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
- package/skills/life-sciences-territory-configure/SKILL.md +217 -0
- package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
- package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
- package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
- package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
- package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
- package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
- package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
- package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
- package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
- package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
- package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
- package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
- package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
- package/skills/service-agentforce-channel-configure/SKILL.md +33 -28
- package/skills/service-agentforce-human-escalation-configure/SKILL.md +205 -0
- package/skills/service-agentforce-human-escalation-configure/assets/escalation-thresholds.instructions.md +37 -0
- package/skills/service-agentforce-human-escalation-configure/assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml +173 -0
- package/skills/service-agentforce-human-escalation-configure/assets/package.xml +8 -0
- package/skills/service-agentforce-human-escalation-configure/assets/sfdx-project.json +5 -0
- package/skills/service-agentforce-human-escalation-configure/references/classifier-contracts.md +103 -0
- package/skills/service-agentforce-human-escalation-configure/references/escalation-mechanism.md +63 -0
- package/skills/service-agentforce-human-escalation-configure/references/failure-policy.md +44 -0
- package/skills/service-agentforce-human-escalation-configure/references/nga-escalation.md +57 -0
- package/skills/service-agentforce-human-escalation-configure/references/runtime-verification.md +72 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/classify-agent-active.mjs +49 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/classify-nga-escalation.mjs +166 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/extract-outbound-route.mjs +67 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/patch-escalation-surfaces.mjs +131 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/__init__.py +0 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +249 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +899 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/verify-and-configure.sh +705 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/verify-escalation-config.mjs +89 -0
- package/skills/service-de-channel-routing-configure/SKILL.md +13 -5
- package/skills/service-de-channel-routing-configure/scripts/tests/test_skill_contract.py +25 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +23 -10
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +63 -48
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +6 -2
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
- package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
- package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
- package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
- package/skills/service-omni-agent-users-create/SKILL.md +96 -0
- package/skills/service-omni-agent-users-create/assets/create-users.apex.template +80 -0
- package/skills/service-omni-agent-users-create/references/apex-patterns.md +135 -0
- package/skills/service-omni-agent-users-create/references/apex-template-notes.md +40 -0
- package/skills/service-omni-agent-users-create/scripts/detect-and-create.sh +206 -0
- package/skills/service-omni-agent-users-create/scripts/detect-existing.sh +122 -0
- package/skills/service-omni-agent-users-create/scripts/run-create.sh +298 -0
- package/skills/service-omni-agent-users-create/scripts/tests/test_user_create_security.py +171 -0
- package/skills/service-omni-agent-work-sharing-configure/SKILL.md +78 -0
- package/skills/service-omni-agent-work-sharing-configure/references/api-notes.md +31 -0
- package/skills/service-omni-agent-work-sharing-configure/scripts/configure-and-report.sh +186 -0
- package/skills/service-omni-agent-work-sharing-configure/scripts/tests/_bootstrap.py +120 -0
- package/skills/service-omni-agent-work-sharing-configure/scripts/tests/test_agent_work_sharing_contracts.py +93 -0
- package/skills/service-omni-base-settings-configure/SKILL.md +77 -0
- package/skills/service-omni-base-settings-configure/assets/force-app/main/default/settings/OmniChannel.settings-meta.xml +8 -0
- package/skills/service-omni-base-settings-configure/assets/package.xml +8 -0
- package/skills/service-omni-base-settings-configure/assets/sfdx-project.json +12 -0
- package/skills/service-omni-base-settings-configure/references/api-notes.md +121 -0
- package/skills/service-omni-base-settings-configure/scripts/configure-and-report.sh +164 -0
- package/skills/service-omni-base-settings-configure/scripts/detect-existing.sh +69 -0
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +168 -0
- package/skills/service-omni-channel-setup-coordinate/examples/output-templates.md +161 -0
- package/skills/service-omni-channel-setup-coordinate/references/gap-catalog.md +99 -0
- package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +1542 -0
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/__init__.py +0 -0
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/_bootstrap.py +223 -0
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +804 -0
- package/skills/service-omni-command-center-analyze/SKILL.md +84 -0
- package/skills/service-omni-command-center-analyze/references/api-notes.md +54 -0
- package/skills/service-omni-command-center-analyze/scripts/analyze.sh +198 -0
- package/skills/service-omni-command-center-analyze/scripts/tests/_bootstrap.py +115 -0
- package/skills/service-omni-command-center-analyze/scripts/tests/test_command_center_analyze_contracts.py +165 -0
- package/skills/service-omni-permission-set-assign/SKILL.md +88 -0
- package/skills/service-omni-permission-set-assign/assets/package.xml +8 -0
- package/skills/service-omni-permission-set-assign/references/api-notes.md +143 -0
- package/skills/service-omni-permission-set-assign/scripts/verify-and-assign.sh +397 -0
- package/skills/service-omni-presence-status-deploy/SKILL.md +87 -0
- package/skills/service-omni-presence-status-deploy/assets/package.xml +12 -0
- package/skills/service-omni-presence-status-deploy/references/api-notes.md +115 -0
- package/skills/service-omni-presence-status-deploy/scripts/deploy-and-report.sh +422 -0
- package/skills/service-omni-presence-user-config-deploy/SKILL.md +80 -0
- package/skills/service-omni-presence-user-config-deploy/references/api-notes.md +60 -0
- package/skills/service-omni-presence-user-config-deploy/scripts/deploy-and-report.sh +261 -0
- package/skills/service-omni-presence-user-config-deploy/scripts/tests/_bootstrap.py +106 -0
- package/skills/service-omni-presence-user-config-deploy/scripts/tests/test_presence_user_config_contracts.py +142 -0
- package/skills/service-omni-queue-deploy/SKILL.md +91 -0
- package/skills/service-omni-queue-deploy/references/api-notes.md +140 -0
- package/skills/service-omni-queue-deploy/scripts/verify-and-align.sh +470 -0
- package/skills/service-omni-queue-members-assign/SKILL.md +93 -0
- package/skills/service-omni-queue-members-assign/references/api-notes.md +144 -0
- package/skills/service-omni-queue-members-assign/scripts/tests/_bootstrap.py +67 -0
- package/skills/service-omni-queue-members-assign/scripts/tests/test_queue_members_contracts.py +73 -0
- package/skills/service-omni-queue-members-assign/scripts/verify-and-bind.sh +362 -0
- package/skills/service-omni-queue-routing-config-deploy/SKILL.md +101 -0
- package/skills/service-omni-queue-routing-config-deploy/references/api-notes.md +127 -0
- package/skills/service-omni-queue-routing-config-deploy/scripts/tests/_bootstrap.py +90 -0
- package/skills/service-omni-queue-routing-config-deploy/scripts/tests/test_queue_routing_config_contracts.py +70 -0
- package/skills/service-omni-queue-routing-config-deploy/scripts/upsert-and-report.sh +538 -0
- package/skills/service-omni-routing-flow-deploy/SKILL.md +111 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.SkillsBased.flow-meta.xml +94 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.flow-meta.xml +88 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Cases.flow-meta.xml +144 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.SkillsBased.flow-meta.xml +94 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.flow-meta.xml +88 -0
- package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCalls.flow-meta.xml +144 -0
- package/skills/service-omni-routing-flow-deploy/assets/package.xml +11 -0
- package/skills/service-omni-routing-flow-deploy/assets/sfdx-project.json +11 -0
- package/skills/service-omni-routing-flow-deploy/references/api-notes.md +265 -0
- package/skills/service-omni-routing-flow-deploy/scripts/deploy-and-report.sh +684 -0
- package/skills/service-omni-service-channel-configure/SKILL.md +83 -0
- package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Cases.serviceChannel-meta.xml +9 -0
- package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Incidents.serviceChannel-meta.xml +9 -0
- package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/MessagingSessions.serviceChannel-meta.xml +9 -0
- package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/VoiceCalls.serviceChannel-meta.xml +9 -0
- package/skills/service-omni-service-channel-configure/assets/package.xml +11 -0
- package/skills/service-omni-service-channel-configure/assets/sfdx-project.json +12 -0
- package/skills/service-omni-service-channel-configure/references/api-notes.md +84 -0
- package/skills/service-omni-service-channel-configure/scripts/deploy-and-report.sh +383 -0
- package/skills/service-omni-sidebar-configure/SKILL.md +77 -0
- package/skills/service-omni-sidebar-configure/references/api-notes.md +51 -0
- package/skills/service-omni-sidebar-configure/scripts/enable-and-report.sh +315 -0
- package/skills/service-omni-sidebar-configure/scripts/tests/_bootstrap.py +142 -0
- package/skills/service-omni-sidebar-configure/scripts/tests/test_sidebar_contracts.py +139 -0
- package/skills/service-omni-skills-based-routing-configure/SKILL.md +81 -0
- package/skills/service-omni-skills-based-routing-configure/references/api-notes.md +50 -0
- package/skills/service-omni-skills-based-routing-configure/scripts/configure-and-report.sh +270 -0
- package/skills/service-omni-skills-based-routing-configure/scripts/tests/_bootstrap.py +120 -0
- package/skills/service-omni-skills-based-routing-configure/scripts/tests/test_sbr_contracts.py +129 -0
- package/skills/service-omni-supervisor-config-deploy/SKILL.md +97 -0
- package/skills/service-omni-supervisor-config-deploy/assets/force-app/main/default/omniSupervisorConfigs/Omni_Supervisor.omniSupervisorConfig-meta.xml +9 -0
- package/skills/service-omni-supervisor-config-deploy/assets/package.xml +8 -0
- package/skills/service-omni-supervisor-config-deploy/assets/sfdx-project.json +12 -0
- package/skills/service-omni-supervisor-config-deploy/references/api-notes.md +205 -0
- package/skills/service-omni-supervisor-config-deploy/scripts/deploy-and-report.sh +586 -0
- package/skills/service-omni-supervisor-config-deploy/scripts/tests/_bootstrap.py +153 -0
- package/skills/service-omni-supervisor-config-deploy/scripts/tests/test_supervisor_config_contracts.py +116 -0
- package/skills/service-omni-supervisor-permset-assign/SKILL.md +88 -0
- package/skills/service-omni-supervisor-permset-assign/references/api-notes.md +48 -0
- package/skills/service-omni-supervisor-permset-assign/scripts/verify-and-assign.sh +316 -0
- package/skills/service-omni-supervisor-surface-deploy/SKILL.md +85 -0
- package/skills/service-omni-supervisor-surface-deploy/references/api-notes.md +47 -0
- package/skills/service-omni-supervisor-surface-deploy/scripts/deploy-and-report.sh +216 -0
- package/skills/service-omni-supervisor-surface-deploy/scripts/tests/_bootstrap.py +95 -0
- package/skills/service-omni-supervisor-surface-deploy/scripts/tests/test_supervisor_surface_contracts.py +154 -0
- package/skills/service-omni-supervisor-users-create/SKILL.md +92 -0
- package/skills/service-omni-supervisor-users-create/assets/create-supervisors.apex.template +72 -0
- package/skills/service-omni-supervisor-users-create/references/apex-patterns.md +73 -0
- package/skills/service-omni-supervisor-users-create/references/apex-template-notes.md +41 -0
- package/skills/service-omni-supervisor-users-create/scripts/detect-and-create.sh +197 -0
- package/skills/service-omni-supervisor-users-create/scripts/detect-existing.sh +112 -0
- package/skills/service-omni-supervisor-users-create/scripts/run-create.sh +296 -0
- package/skills/service-omni-work-skill-routing-configure/SKILL.md +80 -0
- package/skills/service-omni-work-skill-routing-configure/references/api-notes.md +67 -0
- package/skills/service-omni-work-skill-routing-configure/scripts/configure-and-report.sh +262 -0
- package/skills/service-omni-work-skill-routing-configure/scripts/tests/_bootstrap.py +121 -0
- package/skills/service-omni-work-skill-routing-configure/scripts/tests/test_work_skill_routing_contracts.py +161 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# deploy-and-report.sh - deploy a selected OmniSupervisorConfig (Profile scope + Queue list + Supervisor-user list) in one atomic, production-guarded Metadata deploy (async + poll); idempotent. Args, behavior, exit codes: SKILL.md.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
if [ $# -lt 1 ]; then
|
|
7
|
+
echo '{"error":"Missing required argument: org-alias","usage":"bash deploy-and-report.sh <org-alias> [supervisor_count] [additional_queues_csv] [profiles_csv] [skill_visibility] [config_developer_name]"}' >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
ORG="$1"
|
|
12
|
+
SUPERVISOR_COUNT="${2:-1}"
|
|
13
|
+
ADDITIONAL_QUEUES_CSV="${3:-}"
|
|
14
|
+
SKILL_VISIBILITY_INPUT="${5:-${OMNI_SUPERVISOR_SKILL_VISIBILITY:-}}"
|
|
15
|
+
CONFIG_DEVELOPER_NAME="${6:-${OMNI_SUPERVISOR_CONFIG_DEVELOPER_NAME:-Omni_Supervisor}}"
|
|
16
|
+
CONFIG_MASTER_LABEL_INPUT="${OMNI_SUPERVISOR_CONFIG_MASTER_LABEL:-}"
|
|
17
|
+
|
|
18
|
+
if ! [[ "$CONFIG_DEVELOPER_NAME" =~ ^[A-Za-z][A-Za-z0-9_]{0,79}$ ]]; then
|
|
19
|
+
echo "{\"error\":\"Invalid config_developer_name '$CONFIG_DEVELOPER_NAME'. It must start with a letter and contain only A-Z, a-z, 0-9, or _ (maximum 80 characters).\"}" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
case "$SKILL_VISIBILITY_INPUT" in
|
|
24
|
+
""|AllSkills|AnySkill) ;;
|
|
25
|
+
*)
|
|
26
|
+
echo "{\"error\":\"Invalid skill_visibility '$SKILL_VISIBILITY_INPUT'. Allowed: AllSkills, AnySkill\"}" >&2
|
|
27
|
+
exit 1
|
|
28
|
+
;;
|
|
29
|
+
esac
|
|
30
|
+
|
|
31
|
+
if ! [[ "$SUPERVISOR_COUNT" =~ ^[0-9]+$ ]] || [ "$SUPERVISOR_COUNT" -lt 1 ] || [ "$SUPERVISOR_COUNT" -gt 5 ]; then
|
|
32
|
+
echo "{\"error\":\"Invalid supervisor_count '$SUPERVISOR_COUNT'. Must be integer 1..5\"}" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if ! sf org display --target-org "$ORG" --json >/dev/null 2>&1; then
|
|
37
|
+
echo "{\"error\":\"Org alias '$ORG' is not authenticated.\"}" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
42
|
+
ASSETS_DIR="$(cd "$SCRIPT_DIR/../assets" && pwd)"
|
|
43
|
+
TEMPLATE_XML="$ASSETS_DIR/force-app/main/default/omniSupervisorConfigs/Omni_Supervisor.omniSupervisorConfig-meta.xml"
|
|
44
|
+
|
|
45
|
+
emit_blocked() {
|
|
46
|
+
local reason="$1"
|
|
47
|
+
local click_path="$2"
|
|
48
|
+
jq -n \
|
|
49
|
+
--arg skill "service-omni-supervisor-config-deploy" \
|
|
50
|
+
--arg reason "$reason" \
|
|
51
|
+
--arg click_path "$click_path" \
|
|
52
|
+
--arg config_developer_name "$CONFIG_DEVELOPER_NAME" \
|
|
53
|
+
'{
|
|
54
|
+
skill: $skill,
|
|
55
|
+
status: "blocked",
|
|
56
|
+
config_developer_name: $config_developer_name,
|
|
57
|
+
config_id: null,
|
|
58
|
+
supervisor_users_bound: [],
|
|
59
|
+
supervisor_users_count: 0,
|
|
60
|
+
queues_bound: [],
|
|
61
|
+
queues_count: 0,
|
|
62
|
+
deploy_id: null,
|
|
63
|
+
state: null,
|
|
64
|
+
manual_actions: [$click_path],
|
|
65
|
+
blocking_issue: $reason
|
|
66
|
+
}'
|
|
67
|
+
exit 1
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# emit read-only plan preview JSON and exit 0 (PLAN_ONLY mode)
|
|
71
|
+
emit_plan() {
|
|
72
|
+
local status="$1"
|
|
73
|
+
local detail="$2"
|
|
74
|
+
jq -n \
|
|
75
|
+
--arg status "$status" \
|
|
76
|
+
--arg detail "$detail" \
|
|
77
|
+
--arg config_developer_name "$CONFIG_DEVELOPER_NAME" \
|
|
78
|
+
'{
|
|
79
|
+
skill: "service-omni-supervisor-config-deploy",
|
|
80
|
+
status: $status,
|
|
81
|
+
plan_mode: true,
|
|
82
|
+
plan_detail: $detail,
|
|
83
|
+
config_developer_name: $config_developer_name,
|
|
84
|
+
manual_actions: [],
|
|
85
|
+
blocking_issue: null
|
|
86
|
+
}'
|
|
87
|
+
exit 0
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Safe-to-write guard: sandbox / CDO / trial / DE only
|
|
91
|
+
ORG_JSON=$(sf data query --target-org "$ORG" --json \
|
|
92
|
+
-q "SELECT Id, IsSandbox, TrialExpirationDate, OrganizationType FROM Organization LIMIT 1") || {
|
|
93
|
+
emit_blocked "Failed to query Organization for safe_to_write guard." "Verify org auth: sf org display --target-org $ORG"
|
|
94
|
+
}
|
|
95
|
+
ORG_ID=$(echo "$ORG_JSON" | jq -r '.result.records[0].Id')
|
|
96
|
+
IS_SANDBOX=$(echo "$ORG_JSON" | jq -r '.result.records[0].IsSandbox')
|
|
97
|
+
TRIAL_EXP=$(echo "$ORG_JSON" | jq -r '.result.records[0].TrialExpirationDate')
|
|
98
|
+
ORG_TYPE=$(echo "$ORG_JSON" | jq -r '.result.records[0].OrganizationType')
|
|
99
|
+
|
|
100
|
+
SAFE="false"
|
|
101
|
+
if [ "$IS_SANDBOX" = "true" ]; then SAFE="true"; fi
|
|
102
|
+
if [ "$TRIAL_EXP" != "null" ] && [ "$TRIAL_EXP" != "" ]; then SAFE="true"; fi
|
|
103
|
+
if [ "$ORG_TYPE" = "Developer Edition" ] || [ "$ORG_TYPE" = "Base Edition" ]; then SAFE="true"; fi
|
|
104
|
+
|
|
105
|
+
if [ "$SAFE" != "true" ]; then
|
|
106
|
+
emit_blocked \
|
|
107
|
+
"Refusing to deploy to non-sandbox, non-trial, non-DE org (IsSandbox=$IS_SANDBOX, TrialExpirationDate=$TRIAL_EXP, OrganizationType=$ORG_TYPE). Target a sandbox, CDO, trial, or Developer Edition org." \
|
|
108
|
+
"Verify org type: sf org display --target-org $ORG"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# Org suffix (chars 11-18 of the Org Id, lowercased) scopes the supervisor-user search to THIS org
|
|
112
|
+
# (users-create provisions supervisor{N}.<suffix>@example.com).
|
|
113
|
+
SUFFIX=$(echo -n "${ORG_ID:10:8}" | tr '[:upper:]' '[:lower:]')
|
|
114
|
+
|
|
115
|
+
# Discover supervisor users for THIS org's suffix
|
|
116
|
+
SUPER_USERS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
117
|
+
-q "SELECT Id, Username, Profile.Name FROM User WHERE Username LIKE 'supervisor%.${SUFFIX}@example.com' AND IsActive=true ORDER BY Username LIMIT $SUPERVISOR_COUNT" 2>/dev/null || echo '{}')
|
|
118
|
+
|
|
119
|
+
# Distinguish query failure from a clean zero-result: only a parseable records array is authoritative.
|
|
120
|
+
if ! echo "$SUPER_USERS_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
121
|
+
emit_blocked \
|
|
122
|
+
"Supervisor-user discovery query was inconclusive (not a clean result set): $(echo "$SUPER_USERS_JSON" | head -c 200). Not proceeding on an inconclusive read." \
|
|
123
|
+
"Verify org auth and retry"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
FOUND_COUNT=$(echo "$SUPER_USERS_JSON" | jq -r '.result.records | length')
|
|
127
|
+
|
|
128
|
+
# Require the requested number of active supervisors - a partial set would deploy a config that
|
|
129
|
+
# monitors fewer supervisors than the operator asked for, silently under-provisioning.
|
|
130
|
+
if [ "$FOUND_COUNT" -lt "$SUPERVISOR_COUNT" ]; then
|
|
131
|
+
emit_blocked \
|
|
132
|
+
"Expected $SUPERVISOR_COUNT active supervisor user(s) matching 'supervisor{1..N}.${SUFFIX}@example.com'; found only $FOUND_COUNT. Provision or reactivate the missing supervisor users, then rerun this skill." \
|
|
133
|
+
""
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
SUPERVISOR_USERNAMES=$(echo "$SUPER_USERS_JSON" | jq -r '.result.records[].Username')
|
|
137
|
+
SUPERVISOR_IDS=$(echo "$SUPER_USERS_JSON" | jq -r '[.result.records[].Id]')
|
|
138
|
+
|
|
139
|
+
# Build <omniSupervisorConfigUser> blocks
|
|
140
|
+
SUPERVISOR_USERS_XML=""
|
|
141
|
+
while IFS= read -r uname; do
|
|
142
|
+
[ -z "$uname" ] && continue
|
|
143
|
+
SUPERVISOR_USERS_XML+=" <omniSupervisorConfigUser>
|
|
144
|
+
<user>$uname</user>
|
|
145
|
+
</omniSupervisorConfigUser>
|
|
146
|
+
"
|
|
147
|
+
done <<< "$SUPERVISOR_USERNAMES"
|
|
148
|
+
|
|
149
|
+
# Optional <omniSupervisorConfigProfile> companions. Core resolves config by user first, falling back
|
|
150
|
+
# to profile only when a supervisor has no user row; since we bind every supervisor by user, profile
|
|
151
|
+
# companions are omitted by default. Supply a profiles CSV (4th arg) of metadata fullNames to opt in.
|
|
152
|
+
PROFILES_CSV_OVERRIDE="${4:-}"
|
|
153
|
+
PROFILE_SCOPE_XML=""
|
|
154
|
+
RESOLVED_PROFILE_META=""
|
|
155
|
+
if [ -n "$PROFILES_CSV_OVERRIDE" ]; then
|
|
156
|
+
# Only profiles that actually exist on the org can be deployed; a missing one fails the deploy with
|
|
157
|
+
# "no Profile named <X> found", so validate each supplied fullName up front.
|
|
158
|
+
META_PROFILE_FULLNAMES=$(sf org list metadata -m Profile -o "$ORG" --json 2>/dev/null | jq -r '.result[]?.fullName' 2>/dev/null || echo "")
|
|
159
|
+
# `|| true`: grep -v exits 1 when every line is blank (e.g. profiles_csv is just "," ), which under
|
|
160
|
+
# set -euo pipefail would kill the script mid-flight instead of yielding an empty list.
|
|
161
|
+
PROFILE_NAMES=$(printf '%s' "$PROFILES_CSV_OVERRIDE" | tr ',' '\n' | sed 's/^ *//;s/ *$//' | grep -v '^$' || true)
|
|
162
|
+
UNRESOLVED_PROFILES=""
|
|
163
|
+
while IFS= read -r pname; do
|
|
164
|
+
[ -z "$pname" ] && continue
|
|
165
|
+
if ! [[ "$pname" =~ ^[A-Za-z0-9_]{1,80}$ ]]; then
|
|
166
|
+
emit_blocked "Invalid profile fullName '$pname' in profiles_csv (allowed: A-Z a-z 0-9 _; pass metadata fullNames such as Standard,ServiceCloud)." "sf org list metadata -m Profile -o $ORG"
|
|
167
|
+
fi
|
|
168
|
+
if printf '%s\n' "$META_PROFILE_FULLNAMES" | grep -Fxq "$pname"; then
|
|
169
|
+
if ! printf '%s\n' "$RESOLVED_PROFILE_META" | grep -Fxq "$pname"; then
|
|
170
|
+
RESOLVED_PROFILE_META+="$pname
|
|
171
|
+
"
|
|
172
|
+
p_esc=$(printf '%s' "$pname" | sed 's/&/\&/g; s/</\</g; s/>/\>/g')
|
|
173
|
+
PROFILE_SCOPE_XML+=" <omniSupervisorConfigProfile>
|
|
174
|
+
<profile>$p_esc</profile>
|
|
175
|
+
</omniSupervisorConfigProfile>
|
|
176
|
+
"
|
|
177
|
+
fi
|
|
178
|
+
else
|
|
179
|
+
UNRESOLVED_PROFILES+="$pname "
|
|
180
|
+
fi
|
|
181
|
+
done <<< "$PROFILE_NAMES"
|
|
182
|
+
if [ -n "$UNRESOLVED_PROFILES" ]; then
|
|
183
|
+
emit_blocked \
|
|
184
|
+
"profiles_csv contained profile fullName(s) not present on this org: $(printf '%s' "$UNRESOLVED_PROFILES" | sed 's/ *$//'). Pass metadata fullNames that exist (see 'sf org list metadata -m Profile')." \
|
|
185
|
+
"sf org list metadata -m Profile -o $ORG"
|
|
186
|
+
fi
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# Resolve the queues to bind: a caller-supplied CSV is authoritative (actual upstream queues), else
|
|
190
|
+
# fall back to canonical demo names. Either way, verify each queue exists before binding.
|
|
191
|
+
if [ -n "$ADDITIONAL_QUEUES_CSV" ]; then
|
|
192
|
+
IFS=',' read -ra REQUESTED_QUEUES <<< "$ADDITIONAL_QUEUES_CSV"
|
|
193
|
+
ALL_QUEUES=()
|
|
194
|
+
for q in "${REQUESTED_QUEUES[@]}"; do
|
|
195
|
+
q_trimmed=$(echo "$q" | xargs)
|
|
196
|
+
[ -n "$q_trimmed" ] && ALL_QUEUES+=("$q_trimmed")
|
|
197
|
+
done
|
|
198
|
+
QUEUE_SOURCE="caller_supplied"
|
|
199
|
+
else
|
|
200
|
+
ALL_QUEUES=("CaseQueue" "messagingqueue")
|
|
201
|
+
QUEUE_SOURCE="canonical_default"
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
QUEUE_LIST_XML=""
|
|
205
|
+
QUEUES_BOUND_JSON="[]"
|
|
206
|
+
MISSING_QUEUES=()
|
|
207
|
+
for q in "${ALL_QUEUES[@]}"; do
|
|
208
|
+
# Validate DeveloperName shape (SOQL-injection guard) before querying.
|
|
209
|
+
if ! [[ "$q" =~ ^[A-Za-z0-9_]{1,80}$ ]]; then
|
|
210
|
+
emit_blocked "Invalid queue DeveloperName '$q' (allowed: A-Z a-z 0-9 _). Fix the queues argument." "Pass valid queue DeveloperNames"
|
|
211
|
+
fi
|
|
212
|
+
Q_JSON=$(sf data query --target-org "$ORG" --json \
|
|
213
|
+
-q "SELECT Id FROM Group WHERE Type='Queue' AND DeveloperName='$q' LIMIT 1" 2>/dev/null || echo '{}')
|
|
214
|
+
if ! echo "$Q_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
215
|
+
emit_blocked "Queue existence check for '$q' was inconclusive: $(echo "$Q_JSON" | head -c 160). Not proceeding on an inconclusive read." "Verify org auth and retry"
|
|
216
|
+
fi
|
|
217
|
+
Q_EXISTS=$(echo "$Q_JSON" | jq -r '.result.records | length')
|
|
218
|
+
if [ "$Q_EXISTS" -ge 1 ]; then
|
|
219
|
+
QUEUE_LIST_XML+=" <omniSupervisorConfigQueue>
|
|
220
|
+
<queue>$q</queue>
|
|
221
|
+
</omniSupervisorConfigQueue>
|
|
222
|
+
"
|
|
223
|
+
QUEUES_BOUND_JSON=$(echo "$QUEUES_BOUND_JSON" | jq --arg q "$q" '. + [$q]')
|
|
224
|
+
else
|
|
225
|
+
MISSING_QUEUES+=("$q")
|
|
226
|
+
fi
|
|
227
|
+
done
|
|
228
|
+
|
|
229
|
+
QUEUES_COUNT=$(echo "$QUEUES_BOUND_JSON" | jq -r 'length')
|
|
230
|
+
|
|
231
|
+
# Every requested queue must exist; block if ANY is absent (dropping one would under-provision silently).
|
|
232
|
+
if [ "${#MISSING_QUEUES[@]}" -gt 0 ]; then
|
|
233
|
+
emit_blocked \
|
|
234
|
+
"Requested queue(s) not found on org: ${MISSING_QUEUES[*]} (of requested: ${ALL_QUEUES[*]}). Every requested queue must exist before the supervisor config can bind it. Run service-omni-queue-deploy first, or pass only queue DeveloperName(s) that exist as the 3rd argument." \
|
|
235
|
+
"bash ../service-omni-queue-deploy/scripts/verify-and-align.sh $ORG"
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
if [ "$QUEUES_COUNT" -lt 1 ]; then
|
|
239
|
+
emit_blocked \
|
|
240
|
+
"No queues resolved to bind (checked: ${ALL_QUEUES[*]}). Run service-omni-queue-deploy first, or pass the actual queue DeveloperName(s) as the 3rd argument." \
|
|
241
|
+
"bash ../service-omni-queue-deploy/scripts/verify-and-align.sh $ORG"
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# A metadata redeploy replaces the config's Data API action/tab companions. Snapshot every
|
|
245
|
+
# reference-free companion before updating an existing config and restore it after the deploy.
|
|
246
|
+
# Unknown/reference-bearing rows are blocked before deploy because recreating an incomplete row
|
|
247
|
+
# would be worse than leaving the existing config untouched.
|
|
248
|
+
SAFE_ACTIONS="AllAgents.ChangeQueues AllAgents.ChangeSkills AllAgents.ChangeGroups AllAgents.AssignLearning QueuesBacklog.ManageQueues"
|
|
249
|
+
SAFE_TABS="Wallboard Agents QueuesBacklog AssignedWork SkillsBacklog Reports Alerts"
|
|
250
|
+
in_list() {
|
|
251
|
+
local needle="$1"; shift
|
|
252
|
+
local candidate
|
|
253
|
+
for candidate in "$@"; do [ "$candidate" = "$needle" ] && return 0; done
|
|
254
|
+
return 1
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
CFG_EXIST_JSON=$(sf data query --target-org "$ORG" --json \
|
|
258
|
+
-q "SELECT Id, MasterLabel, SkillVisibility FROM OmniSupervisorConfig WHERE DeveloperName='$CONFIG_DEVELOPER_NAME' LIMIT 1" 2>/dev/null || echo '{}')
|
|
259
|
+
if ! echo "$CFG_EXIST_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
260
|
+
emit_blocked "OmniSupervisorConfig discovery was inconclusive. Not deploying because existing skill visibility and surface companions cannot be preserved safely." "Verify org auth and retry"
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
EXISTING_CONFIG_ID=$(echo "$CFG_EXIST_JSON" | jq -r '.result.records[0].Id // ""')
|
|
264
|
+
EXISTING_MASTER_LABEL=$(echo "$CFG_EXIST_JSON" | jq -r '.result.records[0].MasterLabel // ""')
|
|
265
|
+
EXISTING_SKILL_VISIBILITY=$(echo "$CFG_EXIST_JSON" | jq -r '.result.records[0].SkillVisibility // ""')
|
|
266
|
+
CONFIG_MASTER_LABEL="${CONFIG_MASTER_LABEL_INPUT:-${EXISTING_MASTER_LABEL:-${CONFIG_DEVELOPER_NAME//_/ }}}"
|
|
267
|
+
CONFIG_MASTER_LABEL_XML=$(printf '%s' "$CONFIG_MASTER_LABEL" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g')
|
|
268
|
+
SKILL_VISIBILITY="${SKILL_VISIBILITY_INPUT:-${EXISTING_SKILL_VISIBILITY:-AllSkills}}"
|
|
269
|
+
case "$SKILL_VISIBILITY" in
|
|
270
|
+
AllSkills|AnySkill) ;;
|
|
271
|
+
*) emit_blocked "Existing OmniSupervisorConfig has unsupported SkillVisibility '$SKILL_VISIBILITY'; pass AllSkills or AnySkill explicitly as the 5th argument." "Review Omni Supervisor configuration in Setup" ;;
|
|
272
|
+
esac
|
|
273
|
+
|
|
274
|
+
SNAPSHOT_ACTIONS='[]'
|
|
275
|
+
SNAPSHOT_TABS='[]'
|
|
276
|
+
if [ -n "$EXISTING_CONFIG_ID" ]; then
|
|
277
|
+
ACTIONS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
278
|
+
-q "SELECT OmniSupervisorActionType, DisplayOrder FROM OmniSupervisorConfigAction WHERE OmniSupervisorConfigId='$EXISTING_CONFIG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
279
|
+
TABS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
280
|
+
-q "SELECT OmniSupervisorTabType, DisplayOrder FROM OmniSupervisorConfigTab WHERE OmniSupervisorConfigId='$EXISTING_CONFIG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
281
|
+
if ! echo "$ACTIONS_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1 \
|
|
282
|
+
|| ! echo "$TABS_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
283
|
+
emit_blocked "Existing supervisor surface discovery was inconclusive; its actions and tabs cannot be safely restored after a metadata deploy." "Verify OmniSupervisorConfigAction and OmniSupervisorConfigTab access, then retry"
|
|
284
|
+
fi
|
|
285
|
+
SNAPSHOT_ACTIONS=$(echo "$ACTIONS_JSON" | jq -c '[.result.records[] | {type:.OmniSupervisorActionType, order:.DisplayOrder}]')
|
|
286
|
+
SNAPSHOT_TABS=$(echo "$TABS_JSON" | jq -c '[.result.records[] | {type:.OmniSupervisorTabType, order:.DisplayOrder}]')
|
|
287
|
+
while IFS= read -r surface_type; do
|
|
288
|
+
[ -z "$surface_type" ] && continue
|
|
289
|
+
if ! in_list "$surface_type" $SAFE_ACTIONS; then
|
|
290
|
+
emit_blocked "Existing supervisor action '$surface_type' cannot be safely restored by this skill; no deploy was attempted." "Preserve or reconfigure this action manually in Setup"
|
|
291
|
+
fi
|
|
292
|
+
done < <(echo "$SNAPSHOT_ACTIONS" | jq -r '.[].type')
|
|
293
|
+
while IFS= read -r surface_type; do
|
|
294
|
+
[ -z "$surface_type" ] && continue
|
|
295
|
+
if ! in_list "$surface_type" $SAFE_TABS; then
|
|
296
|
+
emit_blocked "Existing supervisor tab '$surface_type' cannot be safely restored by this skill; no deploy was attempted." "Preserve or reconfigure this tab manually in Setup"
|
|
297
|
+
fi
|
|
298
|
+
done < <(echo "$SNAPSHOT_TABS" | jq -r '.[].type')
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
# PLAN_ONLY: prerequisites (supervisor users + queues) are validated above; report whether the
|
|
302
|
+
# OmniSupervisorConfig already exists (read-only) and stop before materializing/deploying.
|
|
303
|
+
if [ "${PLAN_ONLY:-}" = "1" ]; then
|
|
304
|
+
if [ -n "$EXISTING_CONFIG_ID" ]; then
|
|
305
|
+
emit_plan "reused" "OmniSupervisorConfig '$CONFIG_DEVELOPER_NAME' already exists; a --run would reconcile supervisor users and $QUEUES_COUNT queue(s), preserve SkillVisibility=$SKILL_VISIBILITY, and restore its existing action/tab surface."
|
|
306
|
+
else
|
|
307
|
+
emit_plan "action_needed" "Would deploy OmniSupervisorConfig '$CONFIG_DEVELOPER_NAME' binding supervisor users + $QUEUES_COUNT queue(s)."
|
|
308
|
+
fi
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
# Materialize the token-substituted deploy artifact under /tmp/ (mktemp -d + 0700; the artifact holds
|
|
312
|
+
# resolved usernames and is removed by the cleanup trap).
|
|
313
|
+
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
314
|
+
umask 077
|
|
315
|
+
mkdir -p /tmp/omni-supervisor-config-deploy
|
|
316
|
+
chmod 700 /tmp/omni-supervisor-config-deploy 2>/dev/null || true
|
|
317
|
+
WORK_DIR="$(mktemp -d "/tmp/omni-supervisor-config-deploy/${STAMP}.XXXXXX")"
|
|
318
|
+
chmod 700 "$WORK_DIR"
|
|
319
|
+
trap 'rm -rf "$WORK_DIR"' EXIT
|
|
320
|
+
mkdir -p "$WORK_DIR/force-app/main/default/omniSupervisorConfigs"
|
|
321
|
+
|
|
322
|
+
cp "$ASSETS_DIR/sfdx-project.json" "$WORK_DIR/sfdx-project.json"
|
|
323
|
+
PACKAGE_CONTENT=$(cat "$ASSETS_DIR/package.xml")
|
|
324
|
+
PACKAGE_CONTENT="${PACKAGE_CONTENT/Omni_Supervisor/$CONFIG_DEVELOPER_NAME}"
|
|
325
|
+
printf '%s' "$PACKAGE_CONTENT" > "$WORK_DIR/package.xml"
|
|
326
|
+
|
|
327
|
+
TEMPLATE_CONTENT=$(cat "$TEMPLATE_XML")
|
|
328
|
+
|
|
329
|
+
RESOLVED_XML="${TEMPLATE_CONTENT/__SUPERVISOR_USERS_XML__/$SUPERVISOR_USERS_XML}"
|
|
330
|
+
RESOLVED_XML="${RESOLVED_XML/__PROFILE_SCOPE_XML__/$PROFILE_SCOPE_XML}"
|
|
331
|
+
RESOLVED_XML="${RESOLVED_XML/__QUEUE_LIST_XML__/$QUEUE_LIST_XML}"
|
|
332
|
+
RESOLVED_XML="${RESOLVED_XML/__SKILL_VISIBILITY__/$SKILL_VISIBILITY}"
|
|
333
|
+
RESOLVED_XML="${RESOLVED_XML/__MASTER_LABEL__/$CONFIG_MASTER_LABEL_XML}"
|
|
334
|
+
|
|
335
|
+
DEPLOY_XML_PATH="$WORK_DIR/force-app/main/default/omniSupervisorConfigs/$CONFIG_DEVELOPER_NAME.omniSupervisorConfig-meta.xml"
|
|
336
|
+
printf '%s' "$RESOLVED_XML" > "$DEPLOY_XML_PATH"
|
|
337
|
+
|
|
338
|
+
# Deploy --async + poll so a synchronous ClientTimeoutError under org load can't produce a false failure.
|
|
339
|
+
cd "$WORK_DIR"
|
|
340
|
+
START_JSON=$(sf project deploy start --manifest package.xml --target-org "$ORG" --async --json 2>/dev/null || true)
|
|
341
|
+
DEPLOY_ID=$(echo "$START_JSON" | jq -r '.result.id // ""')
|
|
342
|
+
|
|
343
|
+
if [ -z "$DEPLOY_ID" ]; then
|
|
344
|
+
RAW_ERR=$(echo "$START_JSON" | jq -c '.result // .' 2>/dev/null | head -c 800)
|
|
345
|
+
emit_blocked \
|
|
346
|
+
"Could not start the OmniSupervisorConfig deploy (no job id returned). Raw: $RAW_ERR" \
|
|
347
|
+
"Retry: sf project deploy start --manifest package.xml --target-org $ORG"
|
|
348
|
+
fi
|
|
349
|
+
|
|
350
|
+
# Poll to a terminal state. Budget ~20 min (80 * 15s) - comfortably above the 705s/1178s
|
|
351
|
+
# retrieves observed on loaded CDOs, and resilient because each report call is non-blocking.
|
|
352
|
+
DEPLOY_JSON="$START_JSON"
|
|
353
|
+
POLL_STATUS=""
|
|
354
|
+
for _ in $(seq 1 80); do
|
|
355
|
+
REPORT_JSON=$(sf project deploy report --job-id "$DEPLOY_ID" --target-org "$ORG" --json 2>/dev/null || true)
|
|
356
|
+
CUR_STATUS=$(echo "$REPORT_JSON" | jq -r '.result.status // ""')
|
|
357
|
+
case "$CUR_STATUS" in
|
|
358
|
+
Succeeded|Failed|SucceededPartial|Canceled)
|
|
359
|
+
DEPLOY_JSON="$REPORT_JSON"; POLL_STATUS="$CUR_STATUS"; break ;;
|
|
360
|
+
esac
|
|
361
|
+
sleep 15
|
|
362
|
+
done
|
|
363
|
+
|
|
364
|
+
if [ -z "$POLL_STATUS" ]; then
|
|
365
|
+
emit_blocked \
|
|
366
|
+
"OmniSupervisorConfig deploy job $DEPLOY_ID did not reach a terminal state within the ~20 min poll budget (server may still be processing under load)." \
|
|
367
|
+
"Check status: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
368
|
+
fi
|
|
369
|
+
|
|
370
|
+
DEPLOY_ID=$(echo "$DEPLOY_JSON" | jq -r '.result.id // ""')
|
|
371
|
+
DEPLOY_STATUS=$(echo "$DEPLOY_JSON" | jq -r '.result.status // .status // ""')
|
|
372
|
+
|
|
373
|
+
# Only a fully "Succeeded" deploy is acceptable (SucceededPartial may mean the config never landed).
|
|
374
|
+
if [ "$DEPLOY_STATUS" != "Succeeded" ]; then
|
|
375
|
+
RAW_ERR=$(echo "$DEPLOY_JSON" | jq -c '.result // .' 2>/dev/null | head -c 800)
|
|
376
|
+
jq -n \
|
|
377
|
+
--arg deploy_id "$DEPLOY_ID" \
|
|
378
|
+
--arg raw "$RAW_ERR" \
|
|
379
|
+
--arg config_developer_name "$CONFIG_DEVELOPER_NAME" \
|
|
380
|
+
'{
|
|
381
|
+
skill: "service-omni-supervisor-config-deploy",
|
|
382
|
+
status: "blocked",
|
|
383
|
+
config_developer_name: $config_developer_name,
|
|
384
|
+
config_id: null,
|
|
385
|
+
supervisor_users_bound: [],
|
|
386
|
+
supervisor_users_count: 0,
|
|
387
|
+
queues_bound: [],
|
|
388
|
+
queues_count: 0,
|
|
389
|
+
deploy_id: $deploy_id,
|
|
390
|
+
state: "Failed",
|
|
391
|
+
manual_actions: [("Inspect deploy: sf project deploy report --job-id " + $deploy_id)],
|
|
392
|
+
blocking_issue: ("Metadata deploy did not succeed. Raw: " + $raw)
|
|
393
|
+
}'
|
|
394
|
+
exit 1
|
|
395
|
+
fi
|
|
396
|
+
|
|
397
|
+
STATE=$(echo "$DEPLOY_JSON" | jq -r --arg config_developer_name "$CONFIG_DEVELOPER_NAME" '.result.files[] | select(.fullName==$config_developer_name and .type=="OmniSupervisorConfig") | .state' | head -1)
|
|
398
|
+
STATE="${STATE:-unknown}"
|
|
399
|
+
|
|
400
|
+
# Map the deploy state to a status. An UNRECOGNIZED state must NOT silently become "reused"
|
|
401
|
+
# (that would mask a component that never actually deployed) - treat it as a hard failure.
|
|
402
|
+
case "$STATE" in
|
|
403
|
+
Unchanged) STATUS="reused" ;;
|
|
404
|
+
Changed) STATUS="updated" ;;
|
|
405
|
+
Created) STATUS="created" ;;
|
|
406
|
+
*)
|
|
407
|
+
emit_blocked \
|
|
408
|
+
"Deploy reported '$DEPLOY_STATUS' but the OmniSupervisorConfig component state was '$STATE' (not Unchanged/Changed/Created). Cannot confirm the config landed." \
|
|
409
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
410
|
+
;;
|
|
411
|
+
esac
|
|
412
|
+
|
|
413
|
+
# Fetch config_id post-deploy (missing Id after success = hard failure). Bounded retry with backoff
|
|
414
|
+
# converts transient latency into a definitive read; the guards below still fail closed.
|
|
415
|
+
CFG_ID=""
|
|
416
|
+
CFG_ID_SLEEP=10
|
|
417
|
+
for cfg_attempt in $(seq 1 5); do
|
|
418
|
+
CFG_JSON=$(sf data query --target-org "$ORG" --json \
|
|
419
|
+
-q "SELECT Id FROM OmniSupervisorConfig WHERE DeveloperName='$CONFIG_DEVELOPER_NAME' LIMIT 1" 2>/dev/null || echo '{}')
|
|
420
|
+
if echo "$CFG_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
421
|
+
CFG_ID=$(echo "$CFG_JSON" | jq -r '.result.records[0].Id // ""')
|
|
422
|
+
[ -n "$CFG_ID" ] && break
|
|
423
|
+
fi
|
|
424
|
+
if [ "$cfg_attempt" -lt 5 ]; then sleep "$CFG_ID_SLEEP"; CFG_ID_SLEEP=$((CFG_ID_SLEEP + 10)); fi
|
|
425
|
+
done
|
|
426
|
+
|
|
427
|
+
if [ -z "$CFG_ID" ]; then
|
|
428
|
+
emit_blocked \
|
|
429
|
+
"Deploy reported '$DEPLOY_STATUS' (state=$STATE) but OmniSupervisorConfig '$CONFIG_DEVELOPER_NAME' is not queryable afterward (after retry) - the config did not persist." \
|
|
430
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
431
|
+
fi
|
|
432
|
+
|
|
433
|
+
# The parent metadata deploy can remove the config's action/tab rows. Restore only the validated
|
|
434
|
+
# snapshot and verify it by re-querying. The companion surface skill remains responsible for adding
|
|
435
|
+
# any new standard rows requested by the coordinator.
|
|
436
|
+
ACTIONS_RESTORED=0
|
|
437
|
+
TABS_RESTORED=0
|
|
438
|
+
CURRENT_ACTIONS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
439
|
+
-q "SELECT OmniSupervisorActionType, DisplayOrder FROM OmniSupervisorConfigAction WHERE OmniSupervisorConfigId='$CFG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
440
|
+
CURRENT_TABS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
441
|
+
-q "SELECT OmniSupervisorTabType, DisplayOrder FROM OmniSupervisorConfigTab WHERE OmniSupervisorConfigId='$CFG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
442
|
+
if ! echo "$CURRENT_ACTIONS_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1 \
|
|
443
|
+
|| ! echo "$CURRENT_TABS_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
444
|
+
emit_blocked "Config deployed, but the post-deploy supervisor surface read was inconclusive; missing rows cannot be restored safely." "Review the Omni Supervisor surface in Setup"
|
|
445
|
+
fi
|
|
446
|
+
while IFS= read -r row; do
|
|
447
|
+
[ -z "$row" ] && continue
|
|
448
|
+
surface_type=$(echo "$row" | jq -r '.type')
|
|
449
|
+
display_order=$(echo "$row" | jq -r '.order')
|
|
450
|
+
if echo "$CURRENT_ACTIONS_JSON" | jq -e --arg type "$surface_type" \
|
|
451
|
+
'any(.result.records[]?; .OmniSupervisorActionType == $type)' >/dev/null 2>&1; then
|
|
452
|
+
continue
|
|
453
|
+
fi
|
|
454
|
+
CREATE_JSON=$(sf data create record --target-org "$ORG" --json \
|
|
455
|
+
--sobject OmniSupervisorConfigAction \
|
|
456
|
+
--values "OmniSupervisorConfigId=$CFG_ID OmniSupervisorActionType=$surface_type DisplayOrder=$display_order" 2>/dev/null || true)
|
|
457
|
+
if [ "$(echo "$CREATE_JSON" | jq -r '.result.success // false' 2>/dev/null)" != "true" ]; then
|
|
458
|
+
emit_blocked "Config deployed, but existing supervisor action '$surface_type' could not be restored." "Restore the action in Omni Supervisor Setup, then retry"
|
|
459
|
+
fi
|
|
460
|
+
ACTIONS_RESTORED=$((ACTIONS_RESTORED + 1))
|
|
461
|
+
done < <(echo "$SNAPSHOT_ACTIONS" | jq -c '.[]')
|
|
462
|
+
while IFS= read -r row; do
|
|
463
|
+
[ -z "$row" ] && continue
|
|
464
|
+
surface_type=$(echo "$row" | jq -r '.type')
|
|
465
|
+
display_order=$(echo "$row" | jq -r '.order')
|
|
466
|
+
if echo "$CURRENT_TABS_JSON" | jq -e --arg type "$surface_type" \
|
|
467
|
+
'any(.result.records[]?; .OmniSupervisorTabType == $type)' >/dev/null 2>&1; then
|
|
468
|
+
continue
|
|
469
|
+
fi
|
|
470
|
+
CREATE_JSON=$(sf data create record --target-org "$ORG" --json \
|
|
471
|
+
--sobject OmniSupervisorConfigTab \
|
|
472
|
+
--values "OmniSupervisorConfigId=$CFG_ID OmniSupervisorTabType=$surface_type DisplayOrder=$display_order" 2>/dev/null || true)
|
|
473
|
+
if [ "$(echo "$CREATE_JSON" | jq -r '.result.success // false' 2>/dev/null)" != "true" ]; then
|
|
474
|
+
emit_blocked "Config deployed, but existing supervisor tab '$surface_type' could not be restored." "Restore the tab in Omni Supervisor Setup, then retry"
|
|
475
|
+
fi
|
|
476
|
+
TABS_RESTORED=$((TABS_RESTORED + 1))
|
|
477
|
+
done < <(echo "$SNAPSHOT_TABS" | jq -c '.[]')
|
|
478
|
+
|
|
479
|
+
VERIFY_ACTIONS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
480
|
+
-q "SELECT OmniSupervisorActionType, DisplayOrder FROM OmniSupervisorConfigAction WHERE OmniSupervisorConfigId='$CFG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
481
|
+
VERIFY_TABS_JSON=$(sf data query --target-org "$ORG" --json \
|
|
482
|
+
-q "SELECT OmniSupervisorTabType, DisplayOrder FROM OmniSupervisorConfigTab WHERE OmniSupervisorConfigId='$CFG_ID' ORDER BY DisplayOrder" 2>/dev/null || echo '{}')
|
|
483
|
+
if ! echo "$VERIFY_ACTIONS_JSON" | jq -e --argjson expected "$SNAPSHOT_ACTIONS" '
|
|
484
|
+
[.result.records[]?.OmniSupervisorActionType] as $actual |
|
|
485
|
+
all($expected[]; (.type as $type | $actual | index($type) != null))' >/dev/null 2>&1 \
|
|
486
|
+
|| ! echo "$VERIFY_TABS_JSON" | jq -e --argjson expected "$SNAPSHOT_TABS" '
|
|
487
|
+
[.result.records[]?.OmniSupervisorTabType] as $actual |
|
|
488
|
+
all($expected[]; (.type as $type | $actual | index($type) != null))' >/dev/null 2>&1; then
|
|
489
|
+
emit_blocked "Config deployed, but post-deploy verification could not confirm every existing supervisor action and tab was restored." "Review the Omni Supervisor surface in Setup"
|
|
490
|
+
fi
|
|
491
|
+
|
|
492
|
+
# Companion-record verification: the parent existing doesn't prove the child user/queue rows landed.
|
|
493
|
+
# Query the child sObjects scoped to this config and require at least the counts we asked to bind.
|
|
494
|
+
# Bounded retry with backoff (children can lag the parent); only a parseable array is authoritative.
|
|
495
|
+
CFG_USER_JSON='{}'
|
|
496
|
+
CFG_USER_COUNT=0
|
|
497
|
+
CFG_USER_SLEEP=10
|
|
498
|
+
for cu_attempt in $(seq 1 5); do
|
|
499
|
+
CFG_USER_JSON=$(sf data query --target-org "$ORG" --json \
|
|
500
|
+
-q "SELECT Id FROM OmniSupervisorConfigUser WHERE OmniSupervisorConfigId='$CFG_ID'" 2>/dev/null || echo '{}')
|
|
501
|
+
if echo "$CFG_USER_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
502
|
+
CFG_USER_COUNT=$(echo "$CFG_USER_JSON" | jq -r '.result.records | length')
|
|
503
|
+
[ "$CFG_USER_COUNT" -ge "$FOUND_COUNT" ] && break
|
|
504
|
+
fi
|
|
505
|
+
if [ "$cu_attempt" -lt 5 ]; then sleep "$CFG_USER_SLEEP"; CFG_USER_SLEEP=$((CFG_USER_SLEEP + 10)); fi
|
|
506
|
+
done
|
|
507
|
+
if ! echo "$CFG_USER_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
508
|
+
emit_blocked \
|
|
509
|
+
"Companion OmniSupervisorConfigUser verification was inconclusive (after retry): $(echo "$CFG_USER_JSON" | head -c 160). Cannot confirm supervisor users bound; not proceeding on an inconclusive read." \
|
|
510
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
511
|
+
fi
|
|
512
|
+
CFG_USER_COUNT=$(echo "$CFG_USER_JSON" | jq -r '.result.records | length')
|
|
513
|
+
|
|
514
|
+
CFG_QUEUE_JSON='{}'
|
|
515
|
+
CFG_QUEUE_COUNT=0
|
|
516
|
+
CFG_QUEUE_SLEEP=10
|
|
517
|
+
for cq_attempt in $(seq 1 5); do
|
|
518
|
+
CFG_QUEUE_JSON=$(sf data query --target-org "$ORG" --json \
|
|
519
|
+
-q "SELECT Id FROM OmniSupervisorConfigQueue WHERE OmniSupervisorConfigId='$CFG_ID'" 2>/dev/null || echo '{}')
|
|
520
|
+
if echo "$CFG_QUEUE_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
521
|
+
CFG_QUEUE_COUNT=$(echo "$CFG_QUEUE_JSON" | jq -r '.result.records | length')
|
|
522
|
+
[ "$CFG_QUEUE_COUNT" -ge "$QUEUES_COUNT" ] && break
|
|
523
|
+
fi
|
|
524
|
+
if [ "$cq_attempt" -lt 5 ]; then sleep "$CFG_QUEUE_SLEEP"; CFG_QUEUE_SLEEP=$((CFG_QUEUE_SLEEP + 10)); fi
|
|
525
|
+
done
|
|
526
|
+
if ! echo "$CFG_QUEUE_JSON" | jq -e '.result.records | arrays' >/dev/null 2>&1; then
|
|
527
|
+
emit_blocked \
|
|
528
|
+
"Companion OmniSupervisorConfigQueue verification was inconclusive (after retry): $(echo "$CFG_QUEUE_JSON" | head -c 160). Cannot confirm queues bound; not proceeding on an inconclusive read." \
|
|
529
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
530
|
+
fi
|
|
531
|
+
CFG_QUEUE_COUNT=$(echo "$CFG_QUEUE_JSON" | jq -r '.result.records | length')
|
|
532
|
+
|
|
533
|
+
if [ "$CFG_USER_COUNT" -lt "$FOUND_COUNT" ]; then
|
|
534
|
+
emit_blocked \
|
|
535
|
+
"Deploy reported '$DEPLOY_STATUS' (state=$STATE) and the parent config persisted, but only $CFG_USER_COUNT of $FOUND_COUNT intended supervisor-user companion record(s) are present on OmniSupervisorConfig '$CFG_ID'. The config is under-provisioned." \
|
|
536
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
537
|
+
fi
|
|
538
|
+
if [ "$CFG_QUEUE_COUNT" -lt "$QUEUES_COUNT" ]; then
|
|
539
|
+
emit_blocked \
|
|
540
|
+
"Deploy reported '$DEPLOY_STATUS' (state=$STATE) and the parent config persisted, but only $CFG_QUEUE_COUNT of $QUEUES_COUNT intended queue companion record(s) are present on OmniSupervisorConfig '$CFG_ID'. The config is under-provisioned." \
|
|
541
|
+
"Inspect deploy: sf project deploy report --job-id $DEPLOY_ID --target-org $ORG"
|
|
542
|
+
fi
|
|
543
|
+
|
|
544
|
+
# Emit skill-report JSON
|
|
545
|
+
jq -n \
|
|
546
|
+
--arg status "$STATUS" \
|
|
547
|
+
--arg config_developer_name "$CONFIG_DEVELOPER_NAME" \
|
|
548
|
+
--arg cfg_id "$CFG_ID" \
|
|
549
|
+
--argjson supervisor_ids "$SUPERVISOR_IDS" \
|
|
550
|
+
--arg supervisor_count "$FOUND_COUNT" \
|
|
551
|
+
--argjson queues_bound "$QUEUES_BOUND_JSON" \
|
|
552
|
+
--arg queues_count "$QUEUES_COUNT" \
|
|
553
|
+
--arg queue_source "$QUEUE_SOURCE" \
|
|
554
|
+
--arg cfg_user_count "$CFG_USER_COUNT" \
|
|
555
|
+
--arg cfg_queue_count "$CFG_QUEUE_COUNT" \
|
|
556
|
+
--arg deploy_id "$DEPLOY_ID" \
|
|
557
|
+
--arg state "$STATE" \
|
|
558
|
+
--arg skill_visibility "$SKILL_VISIBILITY" \
|
|
559
|
+
--argjson actions_snapshot "$(echo "$SNAPSHOT_ACTIONS" | jq 'length')" \
|
|
560
|
+
--argjson actions_restored "$ACTIONS_RESTORED" \
|
|
561
|
+
--argjson tabs_snapshot "$(echo "$SNAPSHOT_TABS" | jq 'length')" \
|
|
562
|
+
--argjson tabs_restored "$TABS_RESTORED" \
|
|
563
|
+
'{
|
|
564
|
+
skill: "service-omni-supervisor-config-deploy",
|
|
565
|
+
status: $status,
|
|
566
|
+
config_developer_name: $config_developer_name,
|
|
567
|
+
config_id: (if $cfg_id == "" then null else $cfg_id end),
|
|
568
|
+
supervisor_users_bound: $supervisor_ids,
|
|
569
|
+
supervisor_users_count: ($supervisor_count | tonumber),
|
|
570
|
+
queues_bound: $queues_bound,
|
|
571
|
+
queues_count: ($queues_count | tonumber),
|
|
572
|
+
queue_source: $queue_source,
|
|
573
|
+
verified_companion_user_count: ($cfg_user_count | tonumber),
|
|
574
|
+
verified_companion_queue_count: ($cfg_queue_count | tonumber),
|
|
575
|
+
deploy_id: $deploy_id,
|
|
576
|
+
state: $state,
|
|
577
|
+
skill_visibility: $skill_visibility,
|
|
578
|
+
surface_preservation: {
|
|
579
|
+
actions_snapshot: $actions_snapshot,
|
|
580
|
+
actions_restored: $actions_restored,
|
|
581
|
+
tabs_snapshot: $tabs_snapshot,
|
|
582
|
+
tabs_restored: $tabs_restored
|
|
583
|
+
},
|
|
584
|
+
manual_actions: [],
|
|
585
|
+
blocking_issue: null
|
|
586
|
+
}'
|