@salesforce/afv-skills 1.30.0 → 1.32.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 (126) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-bot-upgrade/SKILL.md +217 -0
  3. package/skills/agentforce-bot-upgrade/references/extraction-blueprint.md +242 -0
  4. package/skills/agentforce-bot-upgrade/references/generate-agent-spec.md +128 -0
  5. package/skills/agentforce-bot-upgrade/references/handoff-output-format.md +208 -0
  6. package/skills/agentforce-bot-upgrade/references/input-contract.md +101 -0
  7. package/skills/agentforce-bot-upgrade/references/mapping-rules.md +113 -0
  8. package/skills/agentforce-bot-upgrade/references/planner-workflow-reference.md +78 -0
  9. package/skills/agentforce-bot-upgrade/references/post-conversion-enhancements-reference.md +67 -0
  10. package/skills/agentforce-bot-upgrade/references/quality-checklist.md +33 -0
  11. package/skills/agentforce-bot-upgrade/references/sf-cli-bot-reference.md +116 -0
  12. package/skills/data360-code-extension-generate/SKILL.md +15 -2
  13. package/skills/dx-devops-work-item-manage/SKILL.md +270 -0
  14. package/skills/dx-devops-work-item-manage/examples/common-workflows.md +479 -0
  15. package/skills/dx-devops-work-item-manage/references/cli-commands.md +476 -0
  16. package/skills/dx-org-manage/SKILL.md +8 -5
  17. package/skills/dx-org-trial-expiration-check/SKILL.md +239 -0
  18. package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +588 -0
  19. package/skills/dx-pkg-post-install-configure/SKILL.md +184 -0
  20. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +202 -35
  21. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +26 -0
  22. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +15 -0
  23. package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +29 -5
  24. package/skills/experience-ui-bundle-custom-app-generate/references/configure-metadata-custom-application.md +1 -1
  25. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +30 -0
  26. package/skills/experience-ui-bundle-features-generate/SKILL.md +86 -11
  27. package/skills/experience-ui-bundle-features-generate/references/conflict-resolution-schema.json +20 -0
  28. package/skills/experience-ui-bundle-features-generate/scripts/verify-react-bundle.sh +14 -0
  29. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +6 -1
  30. package/skills/experience-ui-bundle-frontend-generate/references/component.md +34 -1
  31. package/skills/experience-ui-bundle-frontend-generate/references/page.md +1 -1
  32. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +19 -8
  33. package/skills/experience-ui-bundle-metadata-generate/references/csp-metadata-format.md +2 -2
  34. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +30 -0
  35. package/skills/experience-ui-bundle-project-generate/SKILL.md +111 -0
  36. package/skills/experience-ui-bundle-project-generate/scripts/flatten-project.mjs +33 -0
  37. package/skills/platform-custom-field-generate/SKILL.md +12 -11
  38. package/skills/platform-custom-field-generate/references/advanced-picklists.md +17 -17
  39. package/skills/platform-custom-lightning-type-generate/SKILL.md +9 -14
  40. package/skills/platform-custom-lightning-type-generate/references/widget-rendition.md +27 -111
  41. package/skills/platform-custom-report-type-generate/SKILL.md +259 -0
  42. package/skills/platform-custom-report-type-generate/examples/AccountProjectsWithTasks.reportType-meta.xml +51 -0
  43. package/skills/platform-custom-report-type-generate/examples/AccountsWithIndustry.reportType-meta.xml +27 -0
  44. package/skills/platform-custom-report-type-generate/examples/AccountsWithProjects.reportType-meta.xml +44 -0
  45. package/skills/platform-custom-report-type-generate/references/category-values.md +32 -0
  46. package/skills/platform-custom-report-type-generate/references/errors-and-troubleshooting.md +24 -0
  47. package/skills/platform-dataspace-access-configure/SKILL.md +318 -0
  48. package/skills/platform-docs-get/SKILL.md +4 -0
  49. package/skills/platform-docs-get/scripts/extract_salesforce_doc.py +78 -13
  50. package/skills/platform-encryption-configure/SKILL.md +122 -0
  51. package/skills/platform-encryption-configure/assets/EncryptionKey.settings-meta.xml +17 -0
  52. package/skills/platform-encryption-configure/assets/PlatformEncryption.settings-meta.xml +15 -0
  53. package/skills/platform-encryption-configure/assets/encrypted-field.field-meta.xml +22 -0
  54. package/skills/platform-encryption-configure/examples/cache-only-keys.settings-meta.xml +11 -0
  55. package/skills/platform-encryption-configure/references/encryption-schemes.md +34 -0
  56. package/skills/platform-encryption-configure/references/key-models.md +34 -0
  57. package/skills/platform-encryption-configure/references/tenant-secret-lifecycle.md +23 -0
  58. package/skills/platform-encryption-configure/scripts/validate-encryption-metadata.sh +54 -0
  59. package/skills/platform-lightning-type-widget-coordinate/SKILL.md +214 -0
  60. package/skills/platform-lightning-type-widget-coordinate/examples/existing-lightning-type-with-widget-prompt.md +80 -0
  61. package/skills/platform-lightning-type-widget-coordinate/examples/new-lightning-type-with-widget-prompt.md +75 -0
  62. package/skills/platform-lightning-type-widget-coordinate/references/build-plan-format.md +67 -0
  63. package/skills/platform-lightning-type-widget-coordinate/references/lightning-type-discovery.md +124 -0
  64. package/skills/platform-lightning-type-widget-coordinate/references/validation-gates.md +130 -0
  65. package/skills/platform-metadata-api-context-get/SKILL.md +13 -10
  66. package/skills/platform-sharing-owd-configure/SKILL.md +142 -0
  67. package/skills/platform-sharing-owd-configure/examples/get_owd_output.md +38 -0
  68. package/skills/platform-sharing-owd-configure/examples/update_owd_output.md +44 -0
  69. package/skills/platform-sharing-owd-configure/references/access_levels.md +49 -0
  70. package/skills/platform-sharing-owd-configure/references/metadata_api_approach.md +69 -0
  71. package/skills/platform-sharing-rules-generate/SKILL.md +89 -19
  72. package/skills/platform-sharing-rules-generate/examples/test-cases.md +381 -0
  73. package/skills/platform-widget-generate/SKILL.md +241 -0
  74. package/skills/platform-widget-generate/examples/conditional.json +73 -0
  75. package/skills/platform-widget-generate/examples/list-with-foreach.json +66 -0
  76. package/skills/platform-widget-generate/examples/single-object.json +64 -0
  77. package/skills/platform-widget-generate/references/schema-from-lightning-type.md +76 -0
  78. package/skills/platform-widget-generate/references/widget-bundle-layout.md +116 -0
  79. package/skills/platform-widget-generate/references/widget-meta-directives.md +130 -0
  80. package/skills/sales-agentforce-pipeline-management-configure/SKILL.md +268 -0
  81. package/skills/sales-agentforce-pipeline-management-configure/assets/field-completion-template.genAiPromptTemplate-meta.xml +141 -0
  82. package/skills/sales-agentforce-pipeline-management-configure/assets/pipeline_management_flow.flow-meta.xml +548 -0
  83. package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.agent +2938 -0
  84. package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.bundle-meta.xml +4 -0
  85. package/skills/sales-agentforce-pipeline-management-configure/assets/sfdx-project.json +12 -0
  86. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/bant.txt +11 -0
  87. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/meddic.txt +11 -0
  88. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/spiced.txt +11 -0
  89. package/skills/sales-agentforce-pipeline-management-configure/examples/custom-prompt-instructions.md +317 -0
  90. package/skills/sales-agentforce-pipeline-management-configure/references/admin-communication.md +355 -0
  91. package/skills/sales-agentforce-pipeline-management-configure/references/agent-creation.md +383 -0
  92. package/skills/sales-agentforce-pipeline-management-configure/references/auth-and-cli.md +146 -0
  93. package/skills/sales-agentforce-pipeline-management-configure/references/automation-matrix.md +23 -0
  94. package/skills/sales-agentforce-pipeline-management-configure/references/autonomous-updates.md +215 -0
  95. package/skills/sales-agentforce-pipeline-management-configure/references/canonical-agent-path.md +75 -0
  96. package/skills/sales-agentforce-pipeline-management-configure/references/data-sources.md +155 -0
  97. package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompt-template.md +120 -0
  98. package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompts.md +149 -0
  99. package/skills/sales-agentforce-pipeline-management-configure/references/flags.md +13 -0
  100. package/skills/sales-agentforce-pipeline-management-configure/references/flow-clone-from-template.md +447 -0
  101. package/skills/sales-agentforce-pipeline-management-configure/references/metadata-inventory.md +330 -0
  102. package/skills/sales-agentforce-pipeline-management-configure/references/opportunity-stages.md +246 -0
  103. package/skills/sales-agentforce-pipeline-management-configure/references/repair-diagnostics.md +265 -0
  104. package/skills/sales-agentforce-pipeline-management-configure/references/setup-order.md +263 -0
  105. package/skills/sales-agentforce-pipeline-management-configure/references/soap-api-enablement.md +528 -0
  106. package/skills/sales-agentforce-pipeline-management-configure/scripts/CHANGES.md +180 -0
  107. package/skills/sales-agentforce-pipeline-management-configure/scripts/README.md +56 -0
  108. package/skills/sales-agentforce-pipeline-management-configure/scripts/add-field-suggestion.sh +679 -0
  109. package/skills/sales-agentforce-pipeline-management-configure/scripts/create-agent.sh +302 -0
  110. package/skills/sales-agentforce-pipeline-management-configure/scripts/create-flow.sh +250 -0
  111. package/skills/sales-agentforce-pipeline-management-configure/scripts/define-agent-access.sh +430 -0
  112. package/skills/sales-agentforce-pipeline-management-configure/scripts/deploy-settings.sh +77 -0
  113. package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-deal-agent.sh +241 -0
  114. package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-prerequisites.sh +538 -0
  115. package/skills/sales-agentforce-pipeline-management-configure/scripts/flow-debug-and-verify.sh +385 -0
  116. package/skills/sales-agentforce-pipeline-management-configure/scripts/retrieve-settings.sh +131 -0
  117. package/skills/sales-agentforce-pipeline-management-configure/scripts/setup-all.sh +2791 -0
  118. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-bundle-publish.sh +189 -0
  119. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-detection.sh +239 -0
  120. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/flow-builder.sh +238 -0
  121. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/psg.sh +48 -0
  122. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/soap.sh +140 -0
  123. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/stage-descriptions.sh +448 -0
  124. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/test-opp.sh +166 -0
  125. package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-all.sh +636 -0
  126. package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-prompt-generation.sh +346 -0
@@ -0,0 +1,636 @@
1
+ #!/bin/bash
2
+
3
+ # Comprehensive verification of Pipeline Management configuration
4
+ #
5
+ # Checks all components and reports status. Run after setup to confirm
6
+ # everything is working, or to diagnose a partially configured org.
7
+ #
8
+ # Usage: ./verify-all.sh <org-alias>
9
+
10
+ set -euo pipefail
11
+
12
+ # sf CLI can emit ANSI color codes inside --json stdout, breaking jq parsing.
13
+ # 2>/dev/null only strips stderr; these env vars are the reliable fix (see PM notes).
14
+ export NO_COLOR=1
15
+ export FORCE_COLOR=0
16
+
17
+ # Source shared libraries
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ source "$SCRIPT_DIR/shared/soap.sh"
20
+ source "$SCRIPT_DIR/shared/agent-detection.sh"
21
+
22
+ ORG_ALIAS="${1:-}"
23
+
24
+ if [[ -z "$ORG_ALIAS" ]]; then
25
+ echo "Error: Missing org alias"
26
+ echo "Usage: $0 <org-alias>"
27
+ exit 1
28
+ fi
29
+
30
+ # Validate org alias (prevent shell injection via metacharacters)
31
+ if [[ ! "$ORG_ALIAS" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]; then
32
+ echo "ERROR: Invalid org alias. Only alphanumeric, dots, hyphens, and underscores allowed (must start with alphanumeric)."
33
+ exit 1
34
+ fi
35
+
36
+ echo "============================================"
37
+ echo " PIPELINE MANAGEMENT CONFIGURATION STATUS"
38
+ echo "============================================"
39
+ echo ""
40
+ echo "Org: $ORG_ALIAS"
41
+ echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"
42
+ echo ""
43
+
44
+ PASS=0
45
+ WARN=0
46
+ FAIL=0
47
+
48
+ check_pass() { echo " [PASS] $1"; PASS=$((PASS + 1)); }
49
+ check_warn() { echo " [WARN] $1"; WARN=$((WARN + 1)); }
50
+ check_fail() { echo " [FAIL] $1"; FAIL=$((FAIL + 1)); }
51
+ check_error() { echo " [ERROR] $1"; echo " $2"; FAIL=$((FAIL + 1)); }
52
+
53
+ # --- Prerequisites ---
54
+ echo "--- Prerequisites ---"
55
+
56
+ # Get auth details for SOAP checks
57
+ INSTANCE_URL=$(sf org display --target-org "$ORG_ALIAS" --json 2>/dev/null | jq -r '.result.instanceUrl // empty' 2>/dev/null || echo "")
58
+
59
+ # Get access token — newer CLI versions redact it in `sf org display --json`
60
+ # so we use `sf org auth show-access-token --json` which always returns the real token
61
+ ACCESS_TOKEN=$(sf org display --target-org "$ORG_ALIAS" --json 2>/dev/null | jq -r '.result.accessToken // empty' 2>/dev/null || echo "")
62
+
63
+ if [[ -z "$ACCESS_TOKEN" || "$ACCESS_TOKEN" == "null" || "$ACCESS_TOKEN" == *"REDACTED"* ]]; then
64
+ ACCESS_TOKEN=$(echo "y" | sf org auth show-access-token --target-org "$ORG_ALIAS" --no-prompt --json 2>/dev/null | jq -r '.result.accessToken // empty' 2>/dev/null || echo "")
65
+ fi
66
+
67
+ if [[ -z "$ACCESS_TOKEN" || "$ACCESS_TOKEN" == "null" ]]; then
68
+ echo " [FAIL] Cannot retrieve access token. Is the org authenticated?"
69
+ echo " Run: sf org login web --instance-url <url> --alias $ORG_ALIAS"
70
+ exit 1
71
+ fi
72
+
73
+ # Check Pipeline Management (SOAP only)
74
+ PM_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
75
+ -H "Content-Type: text/xml; charset=UTF-8" \
76
+ -H "SOAPAction: readMetadata" \
77
+ -d "<?xml version='1.0' encoding='utf-8'?>
78
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
79
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
80
+ <soapenv:Body><met:readMetadata>
81
+ <met:type>SalesDealAgentSettings</met:type>
82
+ <met:fullNames>SalesDealAgent</met:fullNames>
83
+ </met:readMetadata></soapenv:Body>
84
+ </soapenv:Envelope>" 2>/dev/null)
85
+ PM_HTTP_STATUS=$(echo "$PM_RESPONSE" | tail -1)
86
+ PM_XML=$(echo "$PM_RESPONSE" | sed '$d')
87
+ PM_STATUS=$(parse_soap_response "$PM_XML" "enableDealAgent" "$PM_HTTP_STATUS")
88
+
89
+ case "$PM_STATUS" in
90
+ true)
91
+ check_pass "Pipeline Management: enabled"
92
+ ;;
93
+ false)
94
+ check_fail "Pipeline Management: DISABLED"
95
+ echo " → Enable via: Setup → Sales → Pipeline Management → Turn On"
96
+ ;;
97
+ AUTH_ERROR:*)
98
+ check_error "Pipeline Management: Authentication failed" "${PM_STATUS#AUTH_ERROR:}"
99
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
100
+ ;;
101
+ TYPE_UNAVAILABLE:*)
102
+ check_error "Pipeline Management: Not available in this org" "${PM_STATUS#TYPE_UNAVAILABLE:}"
103
+ echo " → Check: org edition and enabled features in Setup"
104
+ ;;
105
+ NETWORK_ERROR)
106
+ check_error "Pipeline Management: Cannot verify (network/service error)" "Check instance URL and connectivity"
107
+ ;;
108
+ *)
109
+ check_fail "Pipeline Management: Unknown status ($PM_STATUS)"
110
+ ;;
111
+ esac
112
+
113
+ # Check Einstein GenAI
114
+ GENAI_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
115
+ -H "Content-Type: text/xml; charset=UTF-8" \
116
+ -H "SOAPAction: readMetadata" \
117
+ -d "<?xml version='1.0' encoding='utf-8'?>
118
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
119
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
120
+ <soapenv:Body><met:readMetadata>
121
+ <met:type>EinsteinGptSettings</met:type>
122
+ <met:fullNames>EinsteinGpt</met:fullNames>
123
+ </met:readMetadata></soapenv:Body>
124
+ </soapenv:Envelope>" 2>/dev/null)
125
+ GENAI_HTTP_STATUS=$(echo "$GENAI_RESPONSE" | tail -1)
126
+ GENAI_XML=$(echo "$GENAI_RESPONSE" | sed '$d')
127
+ GENAI_STATUS=$(parse_soap_response "$GENAI_XML" "enableEinsteinGptPlatform" "$GENAI_HTTP_STATUS")
128
+
129
+ case "$GENAI_STATUS" in
130
+ true)
131
+ check_pass "Einstein Generative AI: enabled"
132
+ ;;
133
+ false)
134
+ check_fail "Einstein Generative AI: DISABLED"
135
+ echo " → Enable via: Setup → Einstein → Einstein Generative AI → Turn On"
136
+ ;;
137
+ AUTH_ERROR:*)
138
+ check_error "Einstein Generative AI: Authentication failed" "${GENAI_STATUS#AUTH_ERROR:}"
139
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
140
+ ;;
141
+ NETWORK_ERROR)
142
+ check_error "Einstein Generative AI: Cannot verify (network/service error)" "Check instance URL and connectivity"
143
+ ;;
144
+ *)
145
+ check_fail "Einstein Generative AI: Unknown status ($GENAI_STATUS)"
146
+ ;;
147
+ esac
148
+
149
+ # Check Agentforce Agent
150
+ COPILOT_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
151
+ -H "Content-Type: text/xml; charset=UTF-8" \
152
+ -H "SOAPAction: readMetadata" \
153
+ -d "<?xml version='1.0' encoding='utf-8'?>
154
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
155
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
156
+ <soapenv:Body><met:readMetadata>
157
+ <met:type>EinsteinCopilotSettings</met:type>
158
+ <met:fullNames>EinsteinCopilot</met:fullNames>
159
+ </met:readMetadata></soapenv:Body>
160
+ </soapenv:Envelope>" 2>/dev/null)
161
+ COPILOT_HTTP_STATUS=$(echo "$COPILOT_RESPONSE" | tail -1)
162
+ COPILOT_XML=$(echo "$COPILOT_RESPONSE" | sed '$d')
163
+ COPILOT_STATUS=$(parse_soap_response "$COPILOT_XML" "enableEinsteinGptCopilot" "$COPILOT_HTTP_STATUS")
164
+
165
+ case "$COPILOT_STATUS" in
166
+ true)
167
+ check_pass "Agentforce Agent: enabled"
168
+ ;;
169
+ false)
170
+ check_fail "Agentforce Agent: DISABLED"
171
+ echo " → Enable via: Setup → Einstein → Agentforce Agent → Turn On"
172
+ ;;
173
+ AUTH_ERROR:*)
174
+ check_error "Agentforce Agent: Authentication failed" "${COPILOT_STATUS#AUTH_ERROR:}"
175
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
176
+ ;;
177
+ NETWORK_ERROR)
178
+ check_error "Agentforce Agent: Cannot verify (network/service error)" "Check instance URL and connectivity"
179
+ ;;
180
+ *)
181
+ check_fail "Agentforce Agent: Unknown status ($COPILOT_STATUS)"
182
+ ;;
183
+ esac
184
+
185
+ # Check Agentforce Studio / Agent Platform (CRITICAL — AgentPlatformSettings
186
+ # .enableAgentPlatform gates the Sales Deal Agent; core rejects Deal Agent
187
+ # enablement when this OrgPreference is off, so a disabled state here explains
188
+ # an otherwise-opaque Deal Agent activation failure).
189
+ AGENT_PLATFORM_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
190
+ -H "Content-Type: text/xml; charset=UTF-8" \
191
+ -H "SOAPAction: readMetadata" \
192
+ -d "<?xml version='1.0' encoding='utf-8'?>
193
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
194
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
195
+ <soapenv:Body><met:readMetadata>
196
+ <met:type>AgentPlatformSettings</met:type>
197
+ <met:fullNames>AgentPlatform</met:fullNames>
198
+ </met:readMetadata></soapenv:Body>
199
+ </soapenv:Envelope>" 2>/dev/null)
200
+ AGENT_PLATFORM_HTTP_STATUS=$(echo "$AGENT_PLATFORM_RESPONSE" | tail -1)
201
+ AGENT_PLATFORM_XML=$(echo "$AGENT_PLATFORM_RESPONSE" | sed '$d')
202
+ AGENT_PLATFORM_STATUS=$(parse_soap_response "$AGENT_PLATFORM_XML" "enableAgentPlatform" "$AGENT_PLATFORM_HTTP_STATUS")
203
+
204
+ case "$AGENT_PLATFORM_STATUS" in
205
+ true)
206
+ check_pass "Agentforce Studio (Agent Platform): enabled"
207
+ ;;
208
+ false)
209
+ check_fail "Agentforce Studio (Agent Platform): DISABLED"
210
+ echo " → Enable via: Setup → Agentforce Studio → Turn On (gates Deal Agent)"
211
+ ;;
212
+ AUTH_ERROR:*)
213
+ check_error "Agentforce Studio (Agent Platform): Authentication failed" "${AGENT_PLATFORM_STATUS#AUTH_ERROR:}"
214
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
215
+ ;;
216
+ NETWORK_ERROR)
217
+ check_error "Agentforce Studio (Agent Platform): Cannot verify (network/service error)" "Check instance URL and connectivity"
218
+ ;;
219
+ *)
220
+ check_fail "Agentforce Studio (Agent Platform): Unknown status ($AGENT_PLATFORM_STATUS)"
221
+ ;;
222
+ esac
223
+
224
+ # Check Opportunity Team (CRITICAL — PM flow uses OpportunityTeamMember; without
225
+ # it, flow deployment fails with an OppTeamMemRec error)
226
+ OPP_TEAM_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
227
+ -H "Content-Type: text/xml; charset=UTF-8" \
228
+ -H "SOAPAction: readMetadata" \
229
+ -d "<?xml version='1.0' encoding='utf-8'?>
230
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
231
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
232
+ <soapenv:Body><met:readMetadata>
233
+ <met:type>OpportunitySettings</met:type>
234
+ <met:fullNames>Opportunity</met:fullNames>
235
+ </met:readMetadata></soapenv:Body>
236
+ </soapenv:Envelope>" 2>/dev/null)
237
+ OPP_TEAM_HTTP_STATUS=$(echo "$OPP_TEAM_RESPONSE" | tail -1)
238
+ OPP_TEAM_XML=$(echo "$OPP_TEAM_RESPONSE" | sed '$d')
239
+ OPP_TEAM_STATUS=$(parse_soap_response "$OPP_TEAM_XML" "enableOpportunityTeam" "$OPP_TEAM_HTTP_STATUS")
240
+
241
+ case "$OPP_TEAM_STATUS" in
242
+ true)
243
+ check_pass "Opportunity Team: enabled"
244
+ ;;
245
+ false)
246
+ check_fail "Opportunity Team: DISABLED (flow deploy fails with OppTeamMemRec error)"
247
+ echo " → Enable via: Setup → Opportunity → Opportunity Team Settings → Turn On"
248
+ ;;
249
+ AUTH_ERROR:*)
250
+ check_error "Opportunity Team: Authentication failed" "${OPP_TEAM_STATUS#AUTH_ERROR:}"
251
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
252
+ ;;
253
+ NETWORK_ERROR)
254
+ check_error "Opportunity Team: Cannot verify (network/service error)" "Check instance URL and connectivity"
255
+ ;;
256
+ *)
257
+ check_fail "Opportunity Team: Unknown status ($OPP_TEAM_STATUS)"
258
+ ;;
259
+ esac
260
+
261
+ # Check Pipeline Inspection
262
+ PI_RESPONSE=$(curl -s -w "\n%{http_code}" "${INSTANCE_URL}/services/Soap/m/64.0" \
263
+ -H "Content-Type: text/xml; charset=UTF-8" \
264
+ -H "SOAPAction: readMetadata" \
265
+ -d "<?xml version='1.0' encoding='utf-8'?>
266
+ <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
267
+ <soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
268
+ <soapenv:Body><met:readMetadata>
269
+ <met:type>OpportunitySettings</met:type>
270
+ <met:fullNames>Opportunity</met:fullNames>
271
+ </met:readMetadata></soapenv:Body>
272
+ </soapenv:Envelope>" 2>/dev/null)
273
+ PI_HTTP_STATUS=$(echo "$PI_RESPONSE" | tail -1)
274
+ PI_XML=$(echo "$PI_RESPONSE" | sed '$d')
275
+ PI_STATUS=$(parse_soap_response "$PI_XML" "enablePipelineInspection" "$PI_HTTP_STATUS")
276
+
277
+ case "$PI_STATUS" in
278
+ true)
279
+ check_pass "Pipeline Inspection: enabled"
280
+ ;;
281
+ false)
282
+ check_warn "Pipeline Inspection: DISABLED (suggestions won't show in UI)"
283
+ ;;
284
+ AUTH_ERROR:*)
285
+ check_error "Pipeline Inspection: Authentication failed" "${PI_STATUS#AUTH_ERROR:}"
286
+ echo " → Fix: sf org login web --instance-url $INSTANCE_URL --alias $ORG_ALIAS"
287
+ ;;
288
+ NETWORK_ERROR)
289
+ check_error "Pipeline Inspection: Cannot verify (network/service error)" "Check instance URL and connectivity"
290
+ ;;
291
+ *)
292
+ check_warn "Pipeline Inspection: Unknown status ($PI_STATUS)"
293
+ ;;
294
+ esac
295
+
296
+ echo ""
297
+
298
+ # --- Agent ---
299
+ echo "--- Agent ---"
300
+
301
+ AGENT_USER=$(sf data query \
302
+ --query "SELECT Id, Username FROM User WHERE Username LIKE '%salesmanagementagentuser%'" \
303
+ --target-org "$ORG_ALIAS" \
304
+ --json 2>/dev/null | jq -r '.result.records[0].Username // empty' 2>/dev/null || echo "")
305
+
306
+ if [[ -n "$AGENT_USER" ]]; then
307
+ check_pass "Agent user: $AGENT_USER"
308
+ else
309
+ check_fail "Agent user: NOT FOUND"
310
+ fi
311
+
312
+ # Detect the PM bot by AgentTemplate — the same field the scheduled flow
313
+ # uses — instead of a hardcoded DeveloperName.
314
+ BOT_DEF=$(pm_bot_developer_name "$ORG_ALIAS")
315
+
316
+ if [[ -n "$BOT_DEF" ]]; then
317
+ check_pass "BotDefinition: $BOT_DEF (matched by AgentTemplate)"
318
+ else
319
+ check_fail "BotDefinition: NOT FOUND — no bot with a PM AgentTemplate (run create-agent.sh)"
320
+ fi
321
+
322
+ echo ""
323
+
324
+ # --- Permission Set Groups ---
325
+ echo "--- Permission Set Groups ---"
326
+
327
+ PSG_COUNT=$(sf data query \
328
+ --query "SELECT Id, DeveloperName FROM PermissionSetGroup WHERE DeveloperName IN ('SalesManagementUserPsg','SalesManagementAgentUserPsg')" \
329
+ --target-org "$ORG_ALIAS" \
330
+ --use-tooling-api \
331
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
332
+ PSG_COUNT="${PSG_COUNT:-0}"
333
+
334
+ # These two PSGs ship with the Agentforce-for-Sales license, so their presence is a
335
+ # license check — NOT a Pipeline Management enablement indicator. The real functional
336
+ # checks are the agent-user PSG assignment and user PSG assignments below.
337
+ if [[ "$PSG_COUNT" -ge 2 ]]; then
338
+ check_pass "Permission Set Groups (license): both present ($PSG_COUNT/2)"
339
+ else
340
+ check_warn "Permission Set Groups (license): only $PSG_COUNT/2 found — org may lack the Agentforce-for-Sales license"
341
+ fi
342
+
343
+ # Check if agent user has PSG
344
+ if [[ -n "$AGENT_USER" ]]; then
345
+ AGENT_USER_ID=$(sf data query \
346
+ --query "SELECT Id FROM User WHERE Username LIKE '%salesmanagementagentuser%'" \
347
+ --target-org "$ORG_ALIAS" \
348
+ --json 2>/dev/null | jq -r '.result.records[0].Id // empty' 2>/dev/null || echo "")
349
+
350
+ if [[ -n "$AGENT_USER_ID" ]]; then
351
+ AGENT_PSG=$(sf data query \
352
+ --query "SELECT Id FROM PermissionSetAssignment WHERE AssigneeId = '${AGENT_USER_ID}' AND PermissionSetGroup.DeveloperName = 'SalesManagementAgentUserPsg'" \
353
+ --target-org "$ORG_ALIAS" \
354
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
355
+ AGENT_PSG="${AGENT_PSG:-0}"
356
+
357
+ if [[ "$AGENT_PSG" -ge 1 ]]; then
358
+ check_pass "Agent PSG assignment: assigned"
359
+ else
360
+ check_warn "Agent PSG assignment: NOT assigned to agent user"
361
+ fi
362
+ fi
363
+ fi
364
+
365
+ # Count users with SalesManagementUserPsg
366
+ USER_PSG_COUNT=$(sf data query \
367
+ --query "SELECT COUNT() FROM PermissionSetAssignment WHERE PermissionSetGroup.DeveloperName = 'SalesManagementUserPsg'" \
368
+ --target-org "$ORG_ALIAS" \
369
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
370
+ USER_PSG_COUNT="${USER_PSG_COUNT:-0}"
371
+
372
+ if [[ "$USER_PSG_COUNT" -ge 1 ]]; then
373
+ check_pass "User PSG assignments: $USER_PSG_COUNT user(s) assigned"
374
+ else
375
+ check_warn "User PSG assignments: 0 users have SalesManagementUserPsg"
376
+ fi
377
+
378
+ echo ""
379
+
380
+ # --- Agent Access (W-23242378) ---
381
+ # Users holding SalesManagementUserPsg can only launch the agent if it is added
382
+ # to "Agent Access" on a permission set. This is done via the custom permset
383
+ # Sales_Agent_Access (SetupEntityAccess -> BotDefinition) linked into the PSG.
384
+ echo "--- Agent Access ---"
385
+
386
+ ACCESS_PS_ID=$(sf data query \
387
+ --query "SELECT Id FROM PermissionSet WHERE Name = 'Sales_Agent_Access'" \
388
+ --target-org "$ORG_ALIAS" \
389
+ --json 2>/dev/null | jq -r '.result.records[0].Id // empty' 2>/dev/null || echo "")
390
+
391
+ if [[ -z "$ACCESS_PS_ID" ]]; then
392
+ check_warn "Agent Access permset: 'Sales_Agent_Access' not found (run define-agent-access.sh)"
393
+ else
394
+ check_pass "Agent Access permset: Sales_Agent_Access"
395
+
396
+ # Is the agent (BotDefinition, matched by AgentTemplate) granted on that permset?
397
+ # Query by AgentTemplate only — the `Id IN (SELECT ... FROM BotVersion)` subquery
398
+ # was removed in de77d520 because it hangs 60+ seconds on some orgs. Active-version
399
+ # verification is reported separately by the BotDefinition check above (line ~270).
400
+ if [[ -n "$BOT_DEF" ]]; then
401
+ BOT_DEF_ID=$(sf data query \
402
+ --query "SELECT Id FROM BotDefinition WHERE AgentTemplate IN (${PM_AGENT_TEMPLATES_SOQL}) ORDER BY LastModifiedDate DESC LIMIT 1" \
403
+ --target-org "$ORG_ALIAS" \
404
+ --json 2>/dev/null | jq -r '.result.records[0].Id // empty' 2>/dev/null || echo "")
405
+
406
+ if [[ -n "$BOT_DEF_ID" ]]; then
407
+ ACCESS_COUNT=$(sf data query \
408
+ --query "SELECT COUNT() FROM SetupEntityAccess WHERE ParentId = '${ACCESS_PS_ID}' AND SetupEntityId = '${BOT_DEF_ID}'" \
409
+ --target-org "$ORG_ALIAS" \
410
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
411
+ ACCESS_COUNT="${ACCESS_COUNT:-0}"
412
+
413
+ if [[ "$ACCESS_COUNT" -ge 1 ]]; then
414
+ check_pass "Agent Access grant: $BOT_DEF added to Sales_Agent_Access"
415
+ else
416
+ check_fail "Agent Access grant: agent NOT in Sales_Agent_Access (users cannot launch agent)"
417
+ fi
418
+ fi
419
+ else
420
+ check_warn "Agent Access grant: BotDefinition absent — cannot verify grant"
421
+ fi
422
+
423
+ # Is the custom permset linked into the managed PSG?
424
+ ACCESS_PSG_ID=$(sf data query \
425
+ --query "SELECT Id FROM PermissionSetGroup WHERE DeveloperName = 'SalesManagementUserPsg'" \
426
+ --target-org "$ORG_ALIAS" \
427
+ --use-tooling-api \
428
+ --json 2>/dev/null | jq -r '.result.records[0].Id // empty' 2>/dev/null || echo "")
429
+
430
+ if [[ -n "$ACCESS_PSG_ID" ]]; then
431
+ COMPONENT_COUNT=$(sf data query \
432
+ --query "SELECT COUNT() FROM PermissionSetGroupComponent WHERE PermissionSetGroupId = '${ACCESS_PSG_ID}' AND PermissionSetId = '${ACCESS_PS_ID}'" \
433
+ --target-org "$ORG_ALIAS" \
434
+ --use-tooling-api \
435
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
436
+ COMPONENT_COUNT="${COMPONENT_COUNT:-0}"
437
+
438
+ if [[ "$COMPONENT_COUNT" -ge 1 ]]; then
439
+ check_pass "Agent Access link: Sales_Agent_Access is a component of SalesManagementUserPsg"
440
+ else
441
+ check_warn "Agent Access link: Sales_Agent_Access not linked into SalesManagementUserPsg (may be assigned directly)"
442
+ fi
443
+ fi
444
+ fi
445
+
446
+ echo ""
447
+
448
+ # --- Schedule-Triggered Flow ---
449
+ echo "--- Schedule-Triggered Flow ---"
450
+
451
+ # Check by SourceTemplateId first
452
+ FLOW_QUERY=$(sf data query \
453
+ --query "SELECT Id, ApiName, IsActive FROM FlowDefinitionView WHERE SourceTemplateId='sales_pipe_mgmt__OppSuggGenSchFlow' AND IsTemplate=false" \
454
+ --target-org "$ORG_ALIAS" \
455
+ --json 2>/dev/null)
456
+
457
+ FLOW_NAME=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null | head -1 || echo "")
458
+ FLOW_ACTIVE=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null | head -1 || echo "")
459
+
460
+ # Fallback: check by naming convention
461
+ if [[ -z "$FLOW_NAME" ]]; then
462
+ FLOW_QUERY=$(sf data query \
463
+ --query "SELECT Id, ApiName, IsActive FROM FlowDefinitionView WHERE ApiName LIKE '%OppSuggGen%' AND IsTemplate=false" \
464
+ --target-org "$ORG_ALIAS" \
465
+ --json 2>/dev/null)
466
+
467
+ FLOW_NAME=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null | head -1 || echo "")
468
+ FLOW_ACTIVE=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null | head -1 || echo "")
469
+ fi
470
+
471
+ # Fallback: check by exact deployed name
472
+ if [[ -z "$FLOW_NAME" ]]; then
473
+ FLOW_QUERY=$(sf data query \
474
+ --query "SELECT Id, ApiName, IsActive FROM FlowDefinitionView WHERE ApiName = 'Process_Field_Update_Suggestions' AND IsTemplate=false" \
475
+ --target-org "$ORG_ALIAS" \
476
+ --json 2>/dev/null)
477
+
478
+ FLOW_NAME=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null | head -1 || echo "")
479
+ FLOW_ACTIVE=$(echo "$FLOW_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null | head -1 || echo "")
480
+ fi
481
+
482
+ if [[ -z "$FLOW_NAME" ]]; then
483
+ check_fail "Schedule flow: NOT FOUND (must clone via Setup UI 'Save As')"
484
+ elif [[ "$FLOW_ACTIVE" == "true" ]]; then
485
+ check_pass "Schedule flow: $FLOW_NAME (ACTIVE)"
486
+ else
487
+ check_warn "Schedule flow: $FLOW_NAME (INACTIVE — needs activation)"
488
+ fi
489
+
490
+ # Check template exists
491
+ TEMPLATE_EXISTS=$(sf data query \
492
+ --query "SELECT Id, ApiName FROM FlowDefinitionView WHERE ApiName LIKE '%OppSuggGen%' AND IsTemplate=true" \
493
+ --target-org "$ORG_ALIAS" \
494
+ --json 2>/dev/null | jq -r '.result.records[0].ApiName // empty' 2>/dev/null || echo "")
495
+
496
+ if [[ -n "$TEMPLATE_EXISTS" ]]; then
497
+ check_pass "Template flow: present"
498
+ else
499
+ check_fail "Template flow: NOT provisioned (Pipeline Management may not be fully enabled)"
500
+ fi
501
+
502
+ echo ""
503
+
504
+ # --- Grounding Flows (managed sales_pipe_mgmt) ---
505
+ # Deactivated grounding flows silently kill all suggestion generation.
506
+ echo "--- Grounding Flows ---"
507
+
508
+ GROUNDING_QUERY=$(sf data query \
509
+ --query "SELECT ApiName, IsActive FROM FlowDefinitionView WHERE NamespacePrefix='sales_pipe_mgmt' AND ApiName IN ('GetOppGroundingData','GetRcmdConvTscp')" \
510
+ --target-org "$ORG_ALIAS" \
511
+ --json 2>/dev/null)
512
+
513
+ for GROUNDING_FLOW in GetOppGroundingData GetRcmdConvTscp; do
514
+ GROUNDING_ACTIVE=$(echo "$GROUNDING_QUERY" | jq -r --arg n "$GROUNDING_FLOW" '.result.records[] | select(.ApiName==$n) | .IsActive' 2>/dev/null | head -1)
515
+ if [[ -z "$GROUNDING_ACTIVE" ]]; then
516
+ check_fail "Grounding flow $GROUNDING_FLOW: NOT FOUND (sales_pipe_mgmt namespace not provisioned)"
517
+ elif [[ "$GROUNDING_ACTIVE" == "true" ]]; then
518
+ check_pass "Grounding flow $GROUNDING_FLOW: ACTIVE"
519
+ else
520
+ check_fail "Grounding flow $GROUNDING_FLOW: INACTIVE (suggestions will not generate)"
521
+ fi
522
+ done
523
+
524
+ echo ""
525
+
526
+ # --- Stage Descriptions ---
527
+ echo "--- Stage Descriptions ---"
528
+
529
+ STAGE_COUNT=$(sf data query \
530
+ --query "SELECT MasterLabel FROM OpportunityStage WHERE IsActive = true" \
531
+ --target-org "$ORG_ALIAS" \
532
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
533
+ STAGE_COUNT="${STAGE_COUNT:-0}"
534
+
535
+ DESC_RESULT=$(sf data query \
536
+ --query "SELECT Id FROM OpptStageDescription" \
537
+ --target-org "$ORG_ALIAS" \
538
+ --use-tooling-api \
539
+ --json 2>/dev/null || echo '{"status":1}')
540
+
541
+ # OpptStageDescription may be inaccessible if PM isn't fully enabled
542
+ if echo "$DESC_RESULT" | grep -qi "INVALID_TYPE\|NOT_FOUND\|sObject type.*not supported"; then
543
+ DESC_COUNT="0"
544
+ check_warn "Stage descriptions: OpptStageDescription not accessible (Pipeline Management may not be fully enabled)"
545
+ else
546
+ DESC_COUNT=$(echo "$DESC_RESULT" | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
547
+ DESC_COUNT="${DESC_COUNT:-0}"
548
+
549
+ if [[ "$DESC_COUNT" -ge "$STAGE_COUNT" && "$DESC_COUNT" -gt 0 ]]; then
550
+ check_pass "Stage descriptions: $DESC_COUNT/$STAGE_COUNT stages described"
551
+ elif [[ "$DESC_COUNT" -gt 0 ]]; then
552
+ check_warn "Stage descriptions: $DESC_COUNT/$STAGE_COUNT stages (some missing — stage suggestions may fail)"
553
+ else
554
+ check_fail "Stage descriptions: NONE configured (stage suggestions will not work)"
555
+ fi
556
+ fi
557
+
558
+ echo ""
559
+
560
+ # --- Data Sources ---
561
+ echo "--- Data Sources ---"
562
+
563
+ NOTE_COUNT=$(sf data query \
564
+ --query "SELECT COUNT() FROM ContentNote WHERE CreatedDate = LAST_N_DAYS:30" \
565
+ --target-org "$ORG_ALIAS" \
566
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
567
+ NOTE_COUNT="${NOTE_COUNT:-0}"
568
+
569
+ if [[ "$NOTE_COUNT" -gt 0 ]]; then
570
+ check_pass "Recent notes (30d): $NOTE_COUNT"
571
+ else
572
+ check_warn "Recent notes (30d): 0 (agent needs notes to generate suggestions)"
573
+ fi
574
+
575
+ OPP_COUNT=$(sf data query \
576
+ --query "SELECT COUNT() FROM Opportunity WHERE IsClosed = false" \
577
+ --target-org "$ORG_ALIAS" \
578
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
579
+ OPP_COUNT="${OPP_COUNT:-0}"
580
+
581
+ if [[ "$OPP_COUNT" -gt 0 ]]; then
582
+ check_pass "Open opportunities: $OPP_COUNT"
583
+ else
584
+ check_warn "Open opportunities: 0 (agent needs open opps to generate suggestions)"
585
+ fi
586
+
587
+ EMAIL_COUNT=$(sf data query \
588
+ --query "SELECT COUNT() FROM EmailMessage WHERE CreatedDate = LAST_N_DAYS:30" \
589
+ --target-org "$ORG_ALIAS" \
590
+ --json 2>/dev/null | jq -r '.result.totalSize // 0' 2>/dev/null | head -1 | tr -cd '0-9' || echo "0")
591
+ EMAIL_COUNT="${EMAIL_COUNT:-0}"
592
+
593
+ if [[ "$EMAIL_COUNT" -gt 0 ]]; then
594
+ check_pass "Recent emails (30d): $EMAIL_COUNT"
595
+ else
596
+ check_warn "Recent emails (30d): 0 (optional — agent can use notes instead)"
597
+ fi
598
+
599
+ echo ""
600
+
601
+ # --- Summary ---
602
+ echo "============================================"
603
+ echo " SUMMARY"
604
+ echo "============================================"
605
+ echo ""
606
+ echo " PASS: $PASS"
607
+ echo " WARN: $WARN"
608
+ echo " FAIL: $FAIL"
609
+ echo ""
610
+
611
+ if [[ "$FAIL" -eq 0 && "$WARN" -eq 0 ]]; then
612
+ echo " Status: FULLY CONFIGURED"
613
+ echo ""
614
+ echo " Pipeline Management is fully operational."
615
+ echo " Suggestions will generate on the next scheduled flow run."
616
+ elif [[ "$FAIL" -eq 0 ]]; then
617
+ echo " Status: CONFIGURED WITH WARNINGS"
618
+ echo ""
619
+ echo " Core functionality is in place. Review warnings above."
620
+ else
621
+ echo " Status: INCOMPLETE — $FAIL issue(s) must be resolved"
622
+ echo ""
623
+ echo " Fix the FAIL items above before Pipeline Management will function."
624
+ echo ""
625
+ echo " Common fixes:"
626
+ [[ "$OPP_TEAM_STATUS" != "true" ]] && echo " - Enable Opportunity Team: ./enable-prerequisites.sh $ORG_ALIAS"
627
+ [[ "$PM_STATUS" != "true" ]] && echo " - Enable Pipeline Management: ./enable-deal-agent.sh $ORG_ALIAS"
628
+ [[ -z "$AGENT_USER" ]] && echo " - Create agent: ./create-agent.sh $ORG_ALIAS"
629
+ [[ -z "$FLOW_NAME" ]] && echo " - Clone flow: Setup UI → Flows → OppSuggGenSchFlow → Save As"
630
+ [[ "${DESC_COUNT:-0}" -eq 0 ]] && echo " - Add stage descriptions: see references/opportunity-stages.md"
631
+
632
+ # Exit with error status when FAIL > 0 (a PM BotDefinition is now REQUIRED)
633
+ exit 1
634
+ fi
635
+
636
+ echo ""