@salesforce/afv-skills 1.31.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 (98) 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/dx-devops-work-item-manage/SKILL.md +270 -0
  13. package/skills/dx-devops-work-item-manage/examples/common-workflows.md +479 -0
  14. package/skills/dx-devops-work-item-manage/references/cli-commands.md +476 -0
  15. package/skills/dx-org-manage/SKILL.md +8 -5
  16. package/skills/dx-org-trial-expiration-check/SKILL.md +239 -0
  17. package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +588 -0
  18. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -9
  19. package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +29 -5
  20. package/skills/experience-ui-bundle-custom-app-generate/references/configure-metadata-custom-application.md +1 -1
  21. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +30 -0
  22. package/skills/experience-ui-bundle-features-generate/SKILL.md +86 -11
  23. package/skills/experience-ui-bundle-features-generate/references/conflict-resolution-schema.json +20 -0
  24. package/skills/experience-ui-bundle-features-generate/scripts/verify-react-bundle.sh +14 -0
  25. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +6 -1
  26. package/skills/experience-ui-bundle-frontend-generate/references/component.md +34 -1
  27. package/skills/experience-ui-bundle-frontend-generate/references/page.md +1 -1
  28. package/skills/experience-ui-bundle-project-generate/SKILL.md +111 -0
  29. package/skills/experience-ui-bundle-project-generate/scripts/flatten-project.mjs +33 -0
  30. package/skills/platform-custom-lightning-type-generate/SKILL.md +9 -14
  31. package/skills/platform-custom-lightning-type-generate/references/widget-rendition.md +27 -111
  32. package/skills/platform-lightning-type-widget-coordinate/SKILL.md +214 -0
  33. package/skills/platform-lightning-type-widget-coordinate/examples/existing-lightning-type-with-widget-prompt.md +80 -0
  34. package/skills/platform-lightning-type-widget-coordinate/examples/new-lightning-type-with-widget-prompt.md +75 -0
  35. package/skills/platform-lightning-type-widget-coordinate/references/build-plan-format.md +67 -0
  36. package/skills/platform-lightning-type-widget-coordinate/references/lightning-type-discovery.md +124 -0
  37. package/skills/platform-lightning-type-widget-coordinate/references/validation-gates.md +130 -0
  38. package/skills/platform-sharing-owd-configure/SKILL.md +142 -0
  39. package/skills/platform-sharing-owd-configure/examples/get_owd_output.md +38 -0
  40. package/skills/platform-sharing-owd-configure/examples/update_owd_output.md +44 -0
  41. package/skills/platform-sharing-owd-configure/references/access_levels.md +49 -0
  42. package/skills/platform-sharing-owd-configure/references/metadata_api_approach.md +69 -0
  43. package/skills/platform-sharing-rules-generate/SKILL.md +89 -19
  44. package/skills/platform-sharing-rules-generate/examples/test-cases.md +381 -0
  45. package/skills/platform-widget-generate/SKILL.md +241 -0
  46. package/skills/platform-widget-generate/examples/conditional.json +73 -0
  47. package/skills/platform-widget-generate/examples/list-with-foreach.json +66 -0
  48. package/skills/platform-widget-generate/examples/single-object.json +64 -0
  49. package/skills/platform-widget-generate/references/schema-from-lightning-type.md +76 -0
  50. package/skills/platform-widget-generate/references/widget-bundle-layout.md +116 -0
  51. package/skills/platform-widget-generate/references/widget-meta-directives.md +130 -0
  52. package/skills/sales-agentforce-pipeline-management-configure/SKILL.md +268 -0
  53. package/skills/sales-agentforce-pipeline-management-configure/assets/field-completion-template.genAiPromptTemplate-meta.xml +141 -0
  54. package/skills/sales-agentforce-pipeline-management-configure/assets/pipeline_management_flow.flow-meta.xml +548 -0
  55. package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.agent +2938 -0
  56. package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.bundle-meta.xml +4 -0
  57. package/skills/sales-agentforce-pipeline-management-configure/assets/sfdx-project.json +12 -0
  58. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/bant.txt +11 -0
  59. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/meddic.txt +11 -0
  60. package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/spiced.txt +11 -0
  61. package/skills/sales-agentforce-pipeline-management-configure/examples/custom-prompt-instructions.md +317 -0
  62. package/skills/sales-agentforce-pipeline-management-configure/references/admin-communication.md +355 -0
  63. package/skills/sales-agentforce-pipeline-management-configure/references/agent-creation.md +383 -0
  64. package/skills/sales-agentforce-pipeline-management-configure/references/auth-and-cli.md +146 -0
  65. package/skills/sales-agentforce-pipeline-management-configure/references/automation-matrix.md +23 -0
  66. package/skills/sales-agentforce-pipeline-management-configure/references/autonomous-updates.md +215 -0
  67. package/skills/sales-agentforce-pipeline-management-configure/references/canonical-agent-path.md +75 -0
  68. package/skills/sales-agentforce-pipeline-management-configure/references/data-sources.md +155 -0
  69. package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompt-template.md +120 -0
  70. package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompts.md +149 -0
  71. package/skills/sales-agentforce-pipeline-management-configure/references/flags.md +13 -0
  72. package/skills/sales-agentforce-pipeline-management-configure/references/flow-clone-from-template.md +447 -0
  73. package/skills/sales-agentforce-pipeline-management-configure/references/metadata-inventory.md +330 -0
  74. package/skills/sales-agentforce-pipeline-management-configure/references/opportunity-stages.md +246 -0
  75. package/skills/sales-agentforce-pipeline-management-configure/references/repair-diagnostics.md +265 -0
  76. package/skills/sales-agentforce-pipeline-management-configure/references/setup-order.md +263 -0
  77. package/skills/sales-agentforce-pipeline-management-configure/references/soap-api-enablement.md +528 -0
  78. package/skills/sales-agentforce-pipeline-management-configure/scripts/CHANGES.md +180 -0
  79. package/skills/sales-agentforce-pipeline-management-configure/scripts/README.md +56 -0
  80. package/skills/sales-agentforce-pipeline-management-configure/scripts/add-field-suggestion.sh +679 -0
  81. package/skills/sales-agentforce-pipeline-management-configure/scripts/create-agent.sh +302 -0
  82. package/skills/sales-agentforce-pipeline-management-configure/scripts/create-flow.sh +250 -0
  83. package/skills/sales-agentforce-pipeline-management-configure/scripts/define-agent-access.sh +430 -0
  84. package/skills/sales-agentforce-pipeline-management-configure/scripts/deploy-settings.sh +77 -0
  85. package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-deal-agent.sh +241 -0
  86. package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-prerequisites.sh +538 -0
  87. package/skills/sales-agentforce-pipeline-management-configure/scripts/flow-debug-and-verify.sh +385 -0
  88. package/skills/sales-agentforce-pipeline-management-configure/scripts/retrieve-settings.sh +131 -0
  89. package/skills/sales-agentforce-pipeline-management-configure/scripts/setup-all.sh +2791 -0
  90. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-bundle-publish.sh +189 -0
  91. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-detection.sh +239 -0
  92. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/flow-builder.sh +238 -0
  93. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/psg.sh +48 -0
  94. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/soap.sh +140 -0
  95. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/stage-descriptions.sh +448 -0
  96. package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/test-opp.sh +166 -0
  97. package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-all.sh +636 -0
  98. package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-prompt-generation.sh +346 -0
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # verify-prompt-generation.sh — Verify a field's prompt template generates suggestions
4
+ #
5
+ # Usage:
6
+ # bash verify-prompt-generation.sh <org-alias> <field> [opportunity-id]
7
+ #
8
+ # Examples:
9
+ # bash verify-prompt-generation.sh my-org NextStep
10
+ # bash verify-prompt-generation.sh my-org Risk__c 006xx000000ABCD
11
+ #
12
+ # ADMIN VERIFICATION TOOL: Tests the field-completion prompt template BEHIND A FIELD
13
+ # by calling the Einstein /generations API directly. Validates the JSON output
14
+ # structure and shows the generated suggestion, helping admins confirm their prompts
15
+ # work. The <field> argument mirrors the docs and setup-all.sh's echoed guidance:
16
+ # pass the Opportunity field API name (NextStep, StageName, or a custom __c field) —
17
+ # NOT a raw template developer name. The field is resolved to the managed/derived
18
+ # template name here, identically to setup-all.sh Phase 4e and add-field-suggestion.sh,
19
+ # so the namespaced managed template is always queried (a bare, un-namespaced managed
20
+ # name returns ENTITY_IS_DELETED). A fully-qualified template dev name is still
21
+ # accepted as-is for power users.
22
+ #
23
+ set -euo pipefail
24
+
25
+ # sf CLI can emit ANSI color codes inside --json stdout, breaking jq parsing.
26
+ # 2>/dev/null only strips stderr; these env vars are the reliable fix (see PM notes).
27
+ export NO_COLOR=1
28
+ export FORCE_COLOR=0
29
+
30
+ # ============================================================
31
+ # Arguments
32
+ # ============================================================
33
+ ORG_ALIAS="${1:-}"
34
+ FIELD_ARG="${2:-}"
35
+ OPP_ID="${3:-}"
36
+ # Must carry the leading "v" — the REST path is /services/data/v64.0/... and a
37
+ # bare "67.0" produces /services/data/67.0/... which 404s. Same 64.0 API version
38
+ # as add-field-suggestion.sh (which also stores it with the leading "v") and
39
+ # setup-all.sh (which stores a bare "64.0" and prepends "v" at each call site).
40
+ API_VERSION="v64.0"
41
+
42
+ if [[ -z "$ORG_ALIAS" || -z "$FIELD_ARG" ]]; then
43
+ cat >&2 <<EOF
44
+ Usage: $0 <org-alias> <field> [opportunity-id]
45
+
46
+ ADMIN VERIFICATION: Verifies the prompt template behind an Opportunity field
47
+ generates correct field suggestions by calling the Einstein API directly and
48
+ validating the JSON response structure.
49
+
50
+ Arguments:
51
+ org-alias Salesforce org alias or username
52
+ field Opportunity field API name (e.g., NextStep, StageName, Risk__c).
53
+ Resolved to its managed/derived prompt template automatically.
54
+ A fully-qualified template dev name is also accepted as-is.
55
+ opportunity-id (Optional) Opportunity ID. If omitted, a test Opportunity
56
+ owned by the current user is created (and a grounding Note
57
+ seeded); otherwise falls back to a user-owned open Opportunity
58
+ (CloseDate within 90 days).
59
+
60
+ Examples:
61
+ $0 connected-seller-home NextStep
62
+ $0 connected-seller-home Risk__c 006SB00000J73XjYAJ
63
+
64
+ Output:
65
+ - Calls /einstein/prompt-templates/{template}/generations
66
+ - Validates JSON structure (FieldName, SuggestedNewValue, Reasoning, etc.)
67
+ - Reports success/failure with suggested value preview
68
+ EOF
69
+ exit 1
70
+ fi
71
+
72
+ # ------------------------------------------------------------
73
+ # Resolve the field to the template dev name the /generations endpoint expects.
74
+ # Kept inline (not sourced) and IDENTICAL to setup-all.sh Phase 4e + the
75
+ # OOTB_MANAGED_TEMPLATE map / dev-name derivation in add-field-suggestion.sh:
76
+ # - NextStep -> sales_pipe_mgmt__RecommendNextStepforOpp (managed)
77
+ # - StageName -> sales_pipe_mgmt__RecommendStageforOpp (managed picklist template)
78
+ # - custom -> Recommend<Field w/o __c, alnum-only>forOpp
79
+ # A value that is already a template dev name (namespaced, or Recommend...forOpp)
80
+ # is used verbatim so power users can still pass a raw template name.
81
+ resolve_template_name() {
82
+ local f="$1"
83
+ # Passthrough only well-formed template dev names (anchored regex, not a glob):
84
+ # a namespaced managed name, or Recommend<alnum>forOpp. A permissive glob would
85
+ # accept malformed input like "RecommendZ for Opp" and defer failure to a cryptic
86
+ # API error; the anchor makes bad names fall through to the case map / API instead.
87
+ if [[ "$f" =~ ^sales_pipe_mgmt__[A-Za-z0-9_]+$ || "$f" =~ ^Recommend[A-Za-z0-9]+forOpp$ ]]; then
88
+ printf '%s' "$f"; return 0
89
+ fi
90
+ case "$f" in
91
+ NextStep) printf 'sales_pipe_mgmt__RecommendNextStepforOpp' ;;
92
+ StageName) printf 'sales_pipe_mgmt__RecommendStageforOpp' ;;
93
+ *) printf 'Recommend%sforOpp' "$(printf '%s' "$f" | sed 's/__c$//' | sed 's/[^A-Za-z0-9]//g')" ;;
94
+ esac
95
+ }
96
+ TEMPLATE_DEV_NAME="$(resolve_template_name "$FIELD_ARG")"
97
+
98
+ # ============================================================
99
+ # Helper Functions
100
+ # ============================================================
101
+ log_info() { echo " [....] $*"; }
102
+ log_pass() { echo " [PASS] $*"; }
103
+ log_fail() { echo " [FAIL] $*" >&2; }
104
+ log_warn() { echo " [WARN] $*"; }
105
+
106
+ die() {
107
+ echo "Error: $*" >&2
108
+ exit 1
109
+ }
110
+
111
+ # Shared test-opp + grounding-note resolution (kept identical to
112
+ # flow-debug-and-verify.sh via this one sourced shared library). Defines
113
+ # resolve_test_opportunity, which sets OPP_ID and seeds/refreshes the note.
114
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
115
+ source "$SCRIPT_DIR/shared/test-opp.sh"
116
+
117
+ # ============================================================
118
+ # Setup
119
+ # ============================================================
120
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
121
+ echo " Pipeline Management Prompt Template Test"
122
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
123
+ echo ""
124
+ echo "Org: $ORG_ALIAS"
125
+ echo "Field: $FIELD_ARG"
126
+ echo "Template: $TEMPLATE_DEV_NAME"
127
+ echo "Opportunity: ${OPP_ID:-<create test opp>}"
128
+ echo ""
129
+
130
+ # ============================================================
131
+ # Get Access Token
132
+ # ============================================================
133
+ log_info "Authenticating to org..."
134
+
135
+ # Use sf org auth show-access-token for CLI v2.x (hides tokens in org display)
136
+ ACCESS_TOKEN=$(sf org auth show-access-token --target-org "$ORG_ALIAS" --json 2>/dev/null | jq -r '.result.accessToken // empty')
137
+ INSTANCE_URL=$(sf org display --target-org "$ORG_ALIAS" --json 2>/dev/null | jq -r '.result.instanceUrl // empty')
138
+
139
+ if [[ -z "$ACCESS_TOKEN" || -z "$INSTANCE_URL" ]]; then
140
+ die "Could not retrieve access token or instance URL. Verify org alias '$ORG_ALIAS' exists."
141
+ fi
142
+
143
+ log_pass "Connected to $INSTANCE_URL"
144
+ echo ""
145
+
146
+ # ============================================================
147
+ # Resolve the target Opportunity (create a user-owned test opp when omitted)
148
+ # ============================================================
149
+ # Pipeline Inspection is owner-scoped, so a suggestion on an opp owned by someone
150
+ # else is invisible to the admin verifying. Prefer creating a fresh test opp owned
151
+ # by the current user; fall back to a user-owned open opp; skip gracefully if none.
152
+ if [[ -z "$OPP_ID" ]]; then
153
+ log_info "No opportunity given — resolving a user-owned test opportunity..."
154
+
155
+ # resolve_test_opportunity (shared lib) reuses/creates the stable [PM-TEST] opp
156
+ # owned by the current user, falls back to a user-owned open opp, and
157
+ # seeds/refreshes the grounding note on whichever resolved — the SAME opp + note
158
+ # the flow-verification path uses (both scripts share this one lib).
159
+ resolve_test_opportunity
160
+
161
+ if [[ -z "$OPP_ID" ]]; then
162
+ log_warn "No eligible opportunity found for the current user."
163
+ echo " To verify: create an open Opportunity owned by you with CloseDate within 90 days,"
164
+ echo " then re-run: $0 $ORG_ALIAS $FIELD_ARG <opportunity-id>"
165
+ echo ""
166
+ log_info "Skipping output verification — no opportunity available"
167
+ exit 0
168
+ fi
169
+ echo ""
170
+ fi
171
+
172
+ # ============================================================
173
+ # Resolve Template Developer Name to API Name/ID
174
+ # ============================================================
175
+ log_info "Looking up prompt template '$TEMPLATE_DEV_NAME'..."
176
+
177
+ # The sf CLI wraps the REST API and handles name resolution
178
+ # We'll use sf api request which accepts the developer name directly
179
+ echo ""
180
+
181
+ # ============================================================
182
+ # Call Einstein Prompt Template API
183
+ # ============================================================
184
+ log_info "Calling Einstein /generations API..."
185
+
186
+ RESPONSE_FILE=$(mktemp)
187
+
188
+ # Use sf api request which handles authentication and name resolution.
189
+ # GUARD the call with `|| CLI_EXIT=$?`: under `set -e` an unguarded non-zero exit
190
+ # would abort the script immediately, making the `$?` capture and the error block
191
+ # below dead code. Capturing the exit status keeps the diagnostic branch live.
192
+ CLI_EXIT=0
193
+ sf api request rest "/services/data/${API_VERSION}/einstein/prompt-templates/${TEMPLATE_DEV_NAME}/generations" \
194
+ --method POST \
195
+ --target-org "$ORG_ALIAS" \
196
+ --body "{\"isPreview\":false,\"inputParams\":{\"valueMap\":{\"Input:Opportunity\":{\"value\":{\"id\":\"${OPP_ID}\"}}}},\"additionalConfig\":{\"numGenerations\":1,\"temperature\":0,\"applicationName\":\"PromptTemplateGenerationsInvocable\"}}" \
197
+ > "$RESPONSE_FILE" 2>&1 || CLI_EXIT=$?
198
+
199
+ # Check the CLI exit status BEFORE filtering. Two reasons:
200
+ # 1. Under `set -e`, an unguarded sed failure below would abort the script
201
+ # before this check runs, turning the diagnostic branch into dead code.
202
+ # 2. On failure the raw response usually holds a non-JSON CLI error that the
203
+ # JSON-only filter would strip — show it verbatim instead of an empty file.
204
+ if [[ "$CLI_EXIT" -ne 0 ]]; then
205
+ log_fail "API call failed (sf CLI exit code: $CLI_EXIT)"
206
+ echo ""
207
+ echo "Response:"
208
+ cat "$RESPONSE_FILE"
209
+ rm -f "$RESPONSE_FILE"
210
+ exit 1
211
+ fi
212
+
213
+ # Filter out CLI warnings from response (keep only lines starting with { or [)
214
+ sed -n '/^[{\[]/,/^[}\]]/p' "$RESPONSE_FILE" > "${RESPONSE_FILE}.clean"
215
+ mv "${RESPONSE_FILE}.clean" "$RESPONSE_FILE"
216
+
217
+ # Check if response file is empty or contains error
218
+ if [[ ! -s "$RESPONSE_FILE" ]]; then
219
+ log_fail "Empty response from API"
220
+ rm -f "$RESPONSE_FILE"
221
+ exit 1
222
+ fi
223
+
224
+ # Check if response contains error
225
+ if jq -e '.[0].errorCode' "$RESPONSE_FILE" >/dev/null 2>&1; then
226
+ ERROR_CODE=$(jq -r '.[0].errorCode' "$RESPONSE_FILE")
227
+ ERROR_MSG=$(jq -r '.[0].message' "$RESPONSE_FILE")
228
+ log_fail "API returned error: $ERROR_CODE - $ERROR_MSG"
229
+ rm -f "$RESPONSE_FILE"
230
+ exit 1
231
+ fi
232
+
233
+ log_pass "API call succeeded"
234
+ echo ""
235
+
236
+ # ============================================================
237
+ # Extract and Validate JSON
238
+ # ============================================================
239
+ log_info "Parsing response..."
240
+
241
+ # Extract the generation text (which itself is JSON)
242
+ GENERATION_TEXT=$(cat "$RESPONSE_FILE" | jq -r '.generations[0].text // empty')
243
+
244
+ if [[ -z "$GENERATION_TEXT" ]]; then
245
+ log_fail "No generation text in response"
246
+ echo ""
247
+ echo "Full Response:"
248
+ cat "$RESPONSE_FILE" | jq '.'
249
+ rm -f "$RESPONSE_FILE"
250
+ exit 1
251
+ fi
252
+
253
+ # Parse the inner JSON
254
+ PARSED_JSON=$(echo "$GENERATION_TEXT" | jq '.' 2>/dev/null || echo "")
255
+
256
+ if [[ -z "$PARSED_JSON" ]]; then
257
+ log_fail "Generation text is not valid JSON"
258
+ echo ""
259
+ echo "Generation Text:"
260
+ echo "$GENERATION_TEXT"
261
+ rm -f "$RESPONSE_FILE"
262
+ exit 1
263
+ fi
264
+
265
+ log_pass "JSON parsing successful"
266
+ echo ""
267
+
268
+ # ============================================================
269
+ # Validate Required Fields
270
+ # ============================================================
271
+ log_info "Validating JSON structure..."
272
+
273
+ REQUIRED_FIELDS=("FieldName" "SuggestedNewValue" "OriginalValue" "Reasoning" "DueDate" "Sources")
274
+ MISSING_FIELDS=()
275
+
276
+ for field in "${REQUIRED_FIELDS[@]}"; do
277
+ if ! echo "$PARSED_JSON" | jq -e ".$field" >/dev/null 2>&1; then
278
+ MISSING_FIELDS+=("$field")
279
+ fi
280
+ done
281
+
282
+ if [[ ${#MISSING_FIELDS[@]} -gt 0 ]]; then
283
+ log_fail "Missing required fields: ${MISSING_FIELDS[*]}"
284
+ echo ""
285
+ echo "Generated JSON:"
286
+ echo "$PARSED_JSON" | jq '.'
287
+ rm -f "$RESPONSE_FILE"
288
+ exit 1
289
+ fi
290
+
291
+ log_pass "All required fields present"
292
+
293
+ # Validate Sources is an array
294
+ SOURCES_COUNT=$(echo "$PARSED_JSON" | jq '.Sources | length // 0')
295
+ if [[ "$SOURCES_COUNT" -eq 0 ]]; then
296
+ log_warn "Sources array is empty (no citations)"
297
+ else
298
+ log_pass "Sources array contains $SOURCES_COUNT citation(s)"
299
+ fi
300
+
301
+ echo ""
302
+
303
+ # ============================================================
304
+ # Display Results
305
+ # ============================================================
306
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
307
+ echo " ✅ TEST PASSED - AI Suggestion Generated"
308
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
309
+ echo ""
310
+
311
+ FIELD_NAME=$(echo "$PARSED_JSON" | jq -r '.FieldName')
312
+ SUGGESTED_VALUE=$(echo "$PARSED_JSON" | jq -r '.SuggestedNewValue')
313
+ REASONING=$(echo "$PARSED_JSON" | jq -r '.Reasoning')
314
+ DUE_DATE=$(echo "$PARSED_JSON" | jq -r '.DueDate')
315
+
316
+ echo "Field: $FIELD_NAME"
317
+ echo "Suggested Value: $SUGGESTED_VALUE"
318
+ echo "Reasoning: $REASONING"
319
+ echo "Due Date: $DUE_DATE"
320
+ echo "Sources: $SOURCES_COUNT citation(s)"
321
+ echo ""
322
+
323
+ # Character length check
324
+ CHAR_COUNT=${#SUGGESTED_VALUE}
325
+ echo "Length Check: $CHAR_COUNT characters"
326
+
327
+ if [[ $CHAR_COUNT -gt 255 ]]; then
328
+ log_warn "Suggested value exceeds 255 characters (may be truncated on field write)"
329
+ fi
330
+
331
+ echo ""
332
+ echo "Full JSON:"
333
+ echo "$PARSED_JSON" | jq '.'
334
+ echo ""
335
+
336
+ # Save response for inspection
337
+ SAVE_PATH="/tmp/prompt-test-${TEMPLATE_DEV_NAME}-$(date +%Y%m%d-%H%M%S).json"
338
+ echo "$PARSED_JSON" | jq '.' > "$SAVE_PATH"
339
+ echo "💾 Full response saved to: $SAVE_PATH"
340
+
341
+ rm -f "$RESPONSE_FILE"
342
+
343
+ echo ""
344
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
345
+ echo " Test Complete"
346
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"