@salesforce/afv-skills 1.58.0 → 1.60.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 (242) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-architecture-analyze/SKILL.md +66 -17
  3. package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
  4. package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
  5. package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
  6. package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
  7. package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
  8. package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
  9. package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
  10. package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
  11. package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
  12. package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
  13. package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
  14. package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
  15. package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
  16. package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
  17. package/skills/agentforce-d360-analyze/SKILL.md +28 -10
  18. package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
  19. package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
  20. package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
  21. package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
  22. package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
  23. package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
  24. package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
  25. package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
  26. package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
  27. package/skills/agentforce-generate/SKILL.md +21 -1
  28. package/skills/agentforce-generate/references/known-issues.md +51 -1
  29. package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
  30. package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
  31. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
  32. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
  33. package/skills/agentforce-persona-generate/SKILL.md +505 -0
  34. package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
  35. package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
  36. package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
  37. package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
  38. package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
  39. package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
  40. package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
  41. package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
  42. package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
  43. package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
  44. package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
  45. package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
  46. package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
  47. package/skills/agentforce-persona-generate/references/attributions.md +36 -0
  48. package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
  49. package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
  50. package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
  51. package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
  52. package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
  53. package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
  54. package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
  55. package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
  56. package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
  57. package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
  58. package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
  59. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
  60. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
  61. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
  62. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
  63. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
  64. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
  65. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
  66. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
  67. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
  68. package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
  69. package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
  70. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
  71. package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
  72. package/skills/data360-schema-get/SKILL.md +3 -3
  73. package/skills/design-systems-slds-validate/references/report-format.md +1 -1
  74. package/skills/dx-app-analytics-query/SKILL.md +8 -8
  75. package/skills/dx-org-manage/SKILL.md +1 -0
  76. package/skills/dx-org-shape-manage/SKILL.md +1 -0
  77. package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
  78. package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
  79. package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
  80. package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
  81. package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
  82. package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
  83. package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
  84. package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
  85. package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
  86. package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
  87. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
  88. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
  89. package/skills/experience-content-media-image-generate/SKILL.md +83 -0
  90. package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
  91. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
  92. package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
  93. package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
  94. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
  95. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
  96. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
  97. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
  98. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
  99. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
  100. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
  101. package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
  102. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
  103. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
  104. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
  105. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
  106. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
  107. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
  108. package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
  109. package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
  110. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
  111. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
  112. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
  113. package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
  114. package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
  115. package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
  116. package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
  117. package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
  118. package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
  119. package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
  120. package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
  121. package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
  122. package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
  123. package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
  124. package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
  125. package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
  126. package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
  127. package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
  128. package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
  129. package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
  130. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
  131. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
  132. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
  133. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
  134. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
  136. package/skills/marketing-message-test/SKILL.md +194 -0
  137. package/skills/marketing-message-test/references/api-contract.md +333 -0
  138. package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
  139. package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
  140. package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
  141. package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
  142. package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
  143. package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
  144. package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
  145. package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
  146. package/skills/platform-apex-logs-debug/SKILL.md +1 -0
  147. package/skills/platform-metadata-deploy/SKILL.md +1 -0
  148. package/skills/platform-models-api-configure/SKILL.md +5 -5
  149. package/skills/platform-soql-query/SKILL.md +1 -0
  150. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
  151. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
  152. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
  153. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
  154. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
  155. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
  156. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
  157. package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
  158. package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
  159. package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
  160. package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
  161. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
  162. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
  163. package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
  164. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
  165. package/skills/tableau-next-asset-create/README.md +65 -0
  166. package/skills/tableau-next-asset-create/SKILL.md +409 -0
  167. package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
  168. package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
  169. package/skills/tableau-next-asset-create/references/alerts.md +111 -0
  170. package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
  171. package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
  172. package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
  173. package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
  174. package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
  175. package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
  176. package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
  177. package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
  178. package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
  179. package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
  180. package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
  181. package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
  182. package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
  183. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
  184. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
  185. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
  186. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
  187. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
  188. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
  189. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
  190. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
  191. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
  192. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
  193. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
  194. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
  195. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
  196. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
  197. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
  198. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
  199. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
  200. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
  201. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
  202. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
  203. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
  204. package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
  205. package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
  206. package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
  207. package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
  208. package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
  209. package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
  210. package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
  211. package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
  212. package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
  213. package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
  214. package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
  215. package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
  216. package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
  217. package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
  218. package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
  219. package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
  220. package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
  221. package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
  222. package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
  223. package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
  224. package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
  225. package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
  226. package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
  227. package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
  228. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
  229. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
  230. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
  231. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
  232. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
  233. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
  234. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
  235. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
  236. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
  237. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
  238. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
  239. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
  240. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
  241. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
  242. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  name: agentforce-generate
3
- description: "Build, modify, audit, repair, optimize, debug, and deploy agents with Agentforce Agent Script. TRIGGER when: user creates, reviews, or changes .agent files or aiAuthoringBundle metadata; asks to fix AgentScript, audit an existing agent, run an AgentScript health check, common-pitfall review, or baseline-versus-candidate repair loop; changes a response, action, subagent, route, state flow, or Agent Spec; previews, debugs, deploys, publishes, or tests agents; uses sf agent generate/preview/publish/test; or manages Agentforce MCP servers, tools, assets, or authentication. DO NOT TRIGGER when: Apex, Flow, Prompt Template, Experience Cloud, or general Salesforce CLI work is unrelated to Agent Script; or the primary input is a production session or trace ID rather than an agent artifact."
3
+ description: "Build, modify, audit, repair, optimize, debug, and deploy agents with Agentforce Agent Script. TRIGGER when: user creates, reviews, or changes .agent files or aiAuthoringBundle metadata; asks to fix AgentScript, audit an existing agent, run an AgentScript health check, common-pitfall review, or baseline-versus-candidate repair loop; changes a response, action, subagent, route, state flow, or Agent Spec; migrates or upgrades a legacy GenAiPlannerBundle Agentforce agent (NOT an Einstein Bot) to an aiAuthoringBundle (Agent Script) agent; previews, debugs, deploys, publishes, or tests agents; uses sf agent generate/preview/publish/test; or manages Agentforce MCP servers, tools, assets, or authentication. DO NOT TRIGGER when: Apex, Flow, Prompt Template, Experience Cloud, or general Salesforce CLI work is unrelated to Agent Script; the source is an Einstein Bot (BotDefinition/BotVersion) — use agentforce-bot-upgrade; or the primary input is a production session or trace ID rather than an agent artifact."
4
4
  metadata:
5
5
  version: "0.11"
6
6
  domains: ["Agentforce"]
7
7
  minApiVersion: "66.0"
8
8
  relatedSkills:
9
+ - "agentforce-bot-upgrade"
9
10
  - "agentforce-observe"
10
11
  - "agentforce-test"
11
12
  - "automation-flow-generate"
@@ -351,6 +352,25 @@ creation, execution, and result analysis. First map the Agent Spec and all
351
352
  reachable routes/actions into coverage targets. Confirm before adding security
352
353
  tests or running tests that can invoke live actions.
353
354
 
355
+ ### Migrate a Legacy Agent to Agent Script
356
+
357
+ User wants to upgrade a legacy `GenAiPlannerBundle` agent into an NGA `AiAuthoringBundle` (Agent Script) agent. May say "migrate my legacy agent", "upgrade to the new builder", "convert agent", "start migration", or mention `genAiPlannerBundle` / `aiAuthoringBundle` migration. (Distinct from Einstein **Bot** upgrades — this covers existing Agentforce **agents**. To convert an Einstein **Bot** into a new agent, use the **agentforce-bot-upgrade** skill instead.)
358
+
359
+ #### Required Steps
360
+
361
+ Read [Upgrade a Legacy Agent to Agent Script](references/upgrade-legacy-agent-to-agentscript.md) for the full workflow, exact commands, and the NGA-vs-legacy discriminator. In brief:
362
+
363
+ 1. **Set up the project** — **Confirm the target org via a selectable menu — never assume the default org** (show `sf org list`, mark the default, require an explicit pick). Confirm a DX project (create one if needed); run all retrieves from inside it.
364
+ 2. **Pick the legacy agent version** — Two-screen selection: choose the agent, then a **non-NGA** version. Exclude versions whose planner `PlannerType` is `Atlas__ConcurrentMultiAgentOrchestration` (already NGA).
365
+ 3. **Migrate via the Connect API** — POST the chosen `botVersionId` to `migrateAgentToNga`. Mutating call; confirm org + id first. Run it in a **subagent** so the large response (inline `agentScript`) does not bloat context — return only `bundleVersionApiName` (+ `conversionWarnings`, `agentResponse`).
366
+ 4. **Retrieve the new bundle** — Pull the `AiAuthoringBundle` into the project (by `bundleVersionApiName`, or map `bundleVersionId → fullName` as fallback).
367
+ 5. **Analyze, optimize, iterate** — The migration is a mechanical transform that ignores Agent Script primitives. Hand off to **Comprehend an Existing Agent**, then **Optimize an Agent**, then validate/preview.
368
+
369
+ #### Reference Files
370
+
371
+ 1. [Upgrade a Legacy Agent to Agent Script](references/upgrade-legacy-agent-to-agentscript.md) — full step-by-step workflow, commands, and discriminator logic
372
+ 2. [Core Language](references/agent-script-core-language.md) — read the migrated `.agent` structure
373
+
354
374
  ### Optimize an Agent
355
375
 
356
376
  1. Read [Core Language](references/agent-script-core-language.md) and scan every
@@ -325,6 +325,56 @@ Unresolved platform bugs, limitations, and edge cases that affect Agent Script d
325
325
 
326
326
  ---
327
327
 
328
+ ### Issue 21: Migration breaks for agents whose developer name ends in `_<digits>`
329
+ - **Status**: WORKAROUND
330
+ - **Date Discovered**: 2026-08-19
331
+ - **Affects**: `migrateAgentToNga` (legacy → NGA) for any agent whose
332
+ `developer_name` ends in an underscore followed by digits — e.g. `Agent_01`,
333
+ `Support_Bot_2`, `Order_Agent_007`. The trailing `_<digits>` pattern is
334
+ `_\d+$`.
335
+ - **Symptom**: The migration call itself may succeed and the migrated agent is
336
+ viewable/editable **in the Agent Builder UI**, but the bundle **cannot be
337
+ worked on from the terminal**. The versioning treatment of the
338
+ `AiAuthoringBundle` is wrong: the tooling conflates the `_<digits>` name suffix
339
+ with a bundle **version** suffix (`<name>_<version>`), so `sf project retrieve`
340
+ / `sf project deploy` / `sf agent validate|publish` mis-resolve the `fullName`
341
+ and version, and edits cannot be round-tripped.
342
+ - **Root Cause**: `AiAuthoringBundle` uses a `<developer_name>_<version>`
343
+ `fullName` convention (see Issue on the retrieve/deploy folder-name trap in
344
+ [upgrade-legacy-agent-to-agentscript.md](upgrade-legacy-agent-to-agentscript.md)).
345
+ When the developer name **itself** ends in `_<digits>`, that trailing segment
346
+ is ambiguous with the version segment, so the bundle's version handling is
347
+ parsed incorrectly.
348
+ - **Workaround**: Rename the agent's `developer_name` to break up the trailing
349
+ digits **before** migrating — insert a non-digit character so the name no
350
+ longer matches `_\d+$`. A minimal change is enough:
351
+ - `Agent_01` → `Agent_v01`
352
+ - `Order_Agent_007` → `Order_Agent_v007`
353
+
354
+ **Warning: Renaming has ripple effects.** The agent is referenced by developer name
355
+ in several places that must all be updated to the new name, or they break:
356
+ - **Email Configurations** for the Agentforce Service Agent (and any other
357
+ channel/config records keyed on the agent name).
358
+ - **Deploy configs** — `package.xml` and any `AiAuthoringBundle` /
359
+ `GenAiPlannerBundle` member entries that name the agent.
360
+ - **Integrations using the Agent API** — any external caller that targets the
361
+ agent by developer name.
362
+
363
+ Because of this blast radius, prefer renaming **before** the agent accrues
364
+ downstream references. This skill migrates agents from the terminal (`sf` CLI /
365
+ source-controlled workflow), so a `_<digits>` developer name is a **hard
366
+ blocker** for it: the rename above is mandatory before the skill can migrate the
367
+ agent. (The Agent Builder UI can still open a migrated `_<digits>` agent for
368
+ viewing — that is platform behavior, not a path this skill offers, and it does
369
+ not remove the terminal round-trip breakage.)
370
+ - **Open Questions**:
371
+ - Will `migrateAgentToNga` / the bundle tooling be fixed to treat a
372
+ `_<digits>`-suffixed developer name distinctly from a version suffix?
373
+ - Is there a supported rename path that cascades to Email Configurations and
374
+ API integrations automatically?
375
+
376
+ ---
377
+
328
378
  ## Resolved Issues
329
379
 
330
380
  ### Issue 16: `connections:` (plural) wrapper block not valid — use `connection messaging:` (singular)
@@ -359,4 +409,4 @@ When an issue is resolved:
359
409
 
360
410
  ---
361
411
 
362
- *Last updated: 2026-03-04*
412
+ *Last updated: 2026-08-19*
@@ -0,0 +1,547 @@
1
+ # Legacy vs NGA Regression Eval
2
+
3
+ Regression-test a migrated Agent Script (**NGA draft**) against the **legacy**
4
+ agent it replaces, across a fixed utterance suite, to verify equivalent routing
5
+ and actions and acceptable (ideally improved) responses. Findings drive edits to
6
+ the draft; the draft is re-tested until it clears the bar.
7
+
8
+ This is the mechanism behind **Step 5d** of
9
+ [upgrade-legacy-agent-to-agentscript.md](upgrade-legacy-agent-to-agentscript.md).
10
+ It is **draft-only**: nothing here publishes, activates, or deploys anything
11
+ without explicit human approval (per [SKILL.md](../SKILL.md) Rule 1). Two bundled
12
+ scripts do the mechanical work — both under this skill's `scripts/`:
13
+
14
+ - `scripts/upgrade-legacy-nga-run-trials.sh` — collects preview trials.
15
+ - `scripts/upgrade-legacy-nga-analyze.py` — emits the comparison report.
16
+
17
+ > **Example values.** Throughout, `Financial_Service_Agent` (the agent
18
+ > api-name/bundle) and `mk-c360a` (an org alias) appear **only as illustrative
19
+ > examples**. Substitute your own agent and org — nothing in the scripts or this
20
+ > doc is agent-, utterance-, or org-specific; all values come from config/env.
21
+
22
+ ## Contents
23
+
24
+ - [Subjects under test](#subjects-under-test)
25
+ - [Prerequisites](#prerequisites)
26
+ - [Configuration and the utterance suite](#configuration-and-the-utterance-suite)
27
+ - [Generating the utterance suite](#generating-the-utterance-suite)
28
+ - [Side-effect safety gate](#side-effect-safety-gate)
29
+ - [Execution mechanics and traps](#execution-mechanics-and-traps)
30
+ - [Rubric #1 — Trace / action equality (mechanical)](#rubric-1--trace--action-equality-mechanical)
31
+ - [Rubric #2 — Response discrepancy (LLM judge)](#rubric-2--response-discrepancy-llm-judge)
32
+ - [Trials, caching, and the canonical response](#trials-caching-and-the-canonical-response)
33
+ - [The report](#the-report)
34
+ - [Iteration loop and stop condition](#iteration-loop-and-stop-condition)
35
+
36
+ ## Subjects under test
37
+
38
+ Three references are in play: the two agents previewed, plus the org.
39
+
40
+ | Role | Selector | How previewed | Frozen? |
41
+ |---|---|---|---|
42
+ | **Legacy** | the classic `BotDefinition` (e.g. `PlannerType = AiCopilot__ReAct`) | `sf agent preview … --api-name <agent>` | **Yes** — must be **Active**; cache its results |
43
+ | **NGA draft** | the `AiAuthoringBundle` (local `.agent`) | `sf agent preview … --authoring-bundle <agent>` (`--simulate-actions` default; `--use-live-actions` to opt in) | **No** — changes as you edit; never cache |
44
+ | Org | an org alias (e.g. `mk-c360a`) | `-o <org-alias>` | — |
45
+
46
+ > **Name collision (by design).** The legacy Bot and the draft bundle typically
47
+ > share the **same** API name (the migration preserves it). Always disambiguate
48
+ > by *flag*, never by the bare name: `--api-name` → legacy (published/activated
49
+ > Bot), `--authoring-bundle` → local draft.
50
+
51
+ ## Prerequisites
52
+
53
+ Assert all four before running trials:
54
+
55
+ 1. **Correct org.** `sf config get target-org --json` may be stale — do not
56
+ trust a default alias. Confirm the intended org with
57
+ `sf org display -o <org-alias> --json`.
58
+ 2. **Legacy has an Active `BotVersion`.** Otherwise `preview start` fails with
59
+ `Bot <id> has no active version.` Activation is a consequential release
60
+ action — **require explicit human approval; never auto-activate.**
61
+ 3. **Draft compiles clean.** `node scripts/index-agent.mjs <agent-file>` (see
62
+ [agentscript-toolchain.md](agentscript-toolchain.md)).
63
+ 4. **`sf` CLI ≥ 2.149.9** (bundles `@salesforce/agents ≥ 2.0.4`). Assert with
64
+ `sf --version`. Below this, the **legacy** local plan trace is written empty
65
+ (`{}`) and Rubric #1 for legacy cannot be verified locally (see
66
+ [Rubric #1](#rubric-1--trace--action-equality-mechanical)). Upgrade with
67
+ `sf update` (or `npm i -g @salesforce/cli@latest`).
68
+
69
+ ## Configuration and the utterance suite
70
+
71
+ All values are overridable; the scripts read the agent and org from **env** so
72
+ nothing is baked in:
73
+
74
+ - `EVAL_AGENT` — the legacy Bot api-name **and** the draft bundle name (they
75
+ collide by design).
76
+ - `EVAL_ORG` — the target-org alias.
77
+ - `EVAL_BASELINE` — path to the accepted-baseline JSON (default
78
+ `agent-eval/baseline.json`; override to taste).
79
+ - `DEMO_CONTACT` — optional; if set, the analyzer asserts the first draft action
80
+ input binds this contact Id.
81
+
82
+ A representative config (example values):
83
+
84
+ ```yaml
85
+ org_alias: mk-c360a # example — use your alias
86
+ legacy:
87
+ api_name: Financial_Service_Agent # example — use your agent
88
+ draft:
89
+ authoring_bundle: Financial_Service_Agent
90
+ use_live_actions: false # default = simulated (safe); true = live side effects (opt in per safety gate)
91
+ trials: 3 # N runs per (subject, utterance)
92
+ demo_contact_id: "0034V00003XcASMQA3" # example — the fixed contact data actions use
93
+ ```
94
+
95
+ The **utterance suite** is data-driven. Each entry carries: `id`, `text`,
96
+ `source` (one of `user | generated`), `spec_status` (one of
97
+ `confirmed | inferred`), `expected_subagent`, `expected_actions`, `side_effects`
98
+ (one of `none | email | lead | escalate`), and `notes`. The `expected_*` columns
99
+ are the **contract**, not a convenience — they encode intent independently of what
100
+ legacy happened to do, so the oracle triangle (below) can report a legacy defect
101
+ as a *win* rather than a regression.
102
+
103
+ `source` records the **utterance's provenance**, independent of the spec. `user`
104
+ marks real traffic the human supplied — **prioritize as must-pass**; `generated`
105
+ marks utterances the skill synthesized to widen coverage (edge cases, robustness
106
+ paths). Provenance sets *importance*; it does not by itself make the `expected_*`
107
+ trustworthy — that is `spec_status`.
108
+
109
+ `spec_status` records confidence in the **`expected_*` contract**, on a separate
110
+ axis from `source`. A user commonly supplies only the utterance `text` and no
111
+ `expected_*`; the skill then **infers** the intended route + actions and marks the
112
+ entry `inferred` — provisional, **pending the user's validation on inspection**.
113
+ Once the human confirms (or authors) the spec it flips to `confirmed`, and only a
114
+ `confirmed` spec anchors the oracle triangle as truth. **Infer from intent — the
115
+ utterance plus the agent's topic/action catalog — never by copying the legacy
116
+ trace**: a spec cloned from legacy makes legacy pass the triangle by construction
117
+ and collapses the legacy-is-a-baseline-not-oracle design. The provenance ×
118
+ confidence combinations:
119
+
120
+ - `user` + `confirmed` — human gave or validated the spec: full oracle, must-pass.
121
+ - `user` + `inferred` — human gave only the utterance; skill proposed the spec; **awaiting the user's sign-off**.
122
+ - `generated` + `inferred` — skill proposed both; awaiting sign-off.
123
+ - `generated` + `confirmed` — skill proposed, human reviewed and accepted.
124
+
125
+ A `SPEC-REVIEW` / `ADJUDICATE` on an `inferred` row most often means the proposed
126
+ spec was wrong — fix the suite entry, don't touch the draft. An example suite:
127
+
128
+ | id | source | spec_status | utterance | expected subagent | expected action(s) | side effects |
129
+ |---|---|---|---|---|---|---|
130
+ | mortgage_faq | user | confirmed | "What's better, a fixed-rate or an adjustable-rate mortgage?" | Financial_Knowledge_Base_Search | Get_Financial_Customer_Details, Answer_Financial_FAQs | none |
131
+ | loan_status | user | inferred | "What is the status of my Personal Loan Application?" | Loan_Application_Status_Query_Snowflake0 | Get_All_Loan_Application_Details | none |
132
+ | cc_fees | user | confirmed | "What are my credit card fees?" | Credit_Card_Assistance0 | Financial_Credit_Card_Customer | none |
133
+ | cc_txns | user | confirmed | "Show me my last 5 credit card transactions" | Credit_Card_Assistance0 | Get_Credit_Card_Transactions_Details | none |
134
+ | product_rec | user | inferred | "Can you recommend a product for me?" | Provide_Product_Recommendations0 | Get_Customer_Product_List | none |
135
+ | offers | user | confirmed | "What offers are available?" | Offers | Financial_Offers_by_Category | none |
136
+ | escalate | generated | confirmed | "I want to speak to a human." | escalation | escalate_to_human | **escalate** |
137
+ | offtopic | generated | inferred | "What's the weather today?" | off_topic | (none) | none |
138
+ | ambiguous | generated | inferred | "help" | ambiguous_question | (none) | none |
139
+ | wrap_up | generated | confirmed | "No thanks, that's all. Bye." | Chat_Wrap_Up2 | Financial_Email_Action_Post_Agent_Chat | **email** |
140
+
141
+ (The rows above are examples from one financial-services agent — replace them
142
+ with utterances for the agent under test. Here the six domain queries are
143
+ `user`-supplied while the four edge cases — escalation, off-topic, ambiguous,
144
+ wrap-up — are `generated` for coverage; `spec_status` marks which `expected_*` are
145
+ `confirmed` versus still `inferred` and awaiting the user's validation — here
146
+ `loan_status`, `product_rec`, `offtopic`, and `ambiguous`.)
147
+
148
+ ## Generating the utterance suite
149
+
150
+ `user`-supplied utterances (real traffic) come first and set the must-pass bar.
151
+ The skill then **generates** additional utterances to close the coverage gaps that
152
+ real traffic leaves open. Generation is **catalog-driven, not free-form**:
153
+ enumerate the agent's topics/subagents and their actions — the same topic/action
154
+ catalog used to infer specs (see
155
+ [Configuration](#configuration-and-the-utterance-suite)) — and synthesize
156
+ utterances so every route and guardrail is exercised. The oracle triangle can only
157
+ *catch* a routing/action regression on a path some utterance actually walks; an
158
+ untested route is invisible to the eval, so generation is fundamentally
159
+ coverage-gap-closing, not invention.
160
+
161
+ **How many — aim for 5–10 initially.** This is a **probing** eval — spin the draft
162
+ against the legacy, surface discrepancies, act on them — **not** a full-coverage
163
+ certification suite. Mind the cost: each utterance runs `trials` × 2 subjects =
164
+ **6 preview sessions** at the default `trials: 3` (legacy is cached after the first
165
+ run, so later iterations re-run only the draft's N — see
166
+ [Trials, caching](#trials-caching-and-the-canonical-response)). So 5–10 utterances
167
+ is ~30–60 preview runs — enough to probe the behavior surface without a marathon.
168
+ Report the scope back to the user, e.g. *"Generated T = 8 utterances covering
169
+ roughly ~30% of the agent's topic/action catalog."* Then let the user decide
170
+ whether to go deeper — the suite grows **on request**, not by default.
171
+
172
+ **Six criteria, in priority order:**
173
+
174
+ 1. **Route coverage (the backbone).** One+ utterance per topic/subagent and per
175
+ distinct action path, so no route goes untested.
176
+ 2. **Boundary / near-miss routing.** Utterances that sit *between* two topics.
177
+ Mis-routing is the top migration regression and only surfaces when you probe the
178
+ decision boundary, not the center of a topic.
179
+ 3. **Guardrail & terminal behaviors.** Off-topic (should deflect/refuse),
180
+ ambiguous/underspecified ("help"), escalation-to-human, wrap-up/goodbye — the
181
+ agent's *edges*, not its domain answers.
182
+ 4. **Side-effect paths.** Anything that fires email / lead / escalate, tagged
183
+ `side_effects` for the [safety gate](#side-effect-safety-gate) before any live
184
+ run. High-risk and high-value: most likely to diverge legacy → draft.
185
+ 5. **Grounding variants.** An utterance that *should* force a retrieval/grounding
186
+ action, paired with one answerable from model knowledge — to catch the "draft
187
+ answered from its own knowledge, legacy grounded" regression that
188
+ [Rubric #2](#rubric-2--response-discrepancy-llm-judge) step 5 is built to flag.
189
+ 6. **Paraphrase robustness.** A couple of phrasings of the same intent — NL routing
190
+ is phrasing-sensitive, so one wording passing does not mean the intent is safe.
191
+
192
+ **Priorities and guardrails:**
193
+
194
+ - **Real traffic first.** `generated` provenance is lower must-pass priority than
195
+ `user` (see [Configuration](#configuration-and-the-utterance-suite)); generate to
196
+ *widen* coverage, never to substitute for what users actually say.
197
+ - **Skew toward hidden behavior.** The happy path is usually already covered by
198
+ real traffic, so the `generated` set earns its keep by probing what the happy
199
+ path won't: guardrail firing, terminal/lifecycle side effects, degenerate input,
200
+ boundary routing — exactly where migrations quietly break (a topic that silently
201
+ stopped matching, a guardrail that stopped firing, a side effect that changed
202
+ shape). Happy-path-only generation makes the eval look green while leaving the
203
+ risky surface untested.
204
+ - **Every generated utterance still needs a spec**, inferred from *intent +
205
+ catalog* and marked `inferred` until the user confirms it — **never cloned from
206
+ the legacy trace** (the anti-circularity rule; see
207
+ [the oracle triangle](#the-oracle-triangle--legacy-is-a-baseline-not-the-source-of-truth)).
208
+ Bare text with no `expected_*` yields only a `SPEC-UNVERIFIED` verdict.
209
+ - **No redundant padding.** Each utterance should test a route, action, boundary,
210
+ or guardrail a prior one didn't; drop duplicates that add trials without adding
211
+ coverage.
212
+
213
+ ## Side-effect safety gate
214
+
215
+ **This gate is mandatory.** In `use_live_actions: true`, some utterances fire
216
+ **real** effects — e.g. `escalate` (transfer to a human), `email`/`wrap_up`
217
+ (sends a customer email), and lead-capture paths (create a Lead + post to Slack).
218
+ Before running trials the skill MUST:
219
+
220
+ - **(a) Tag** every utterance with its `side_effects` category.
221
+ - **(b) Default tagged utterances to simulated mode** (`--simulate-actions` at
222
+ `start`) **or** require explicit per-utterance confirmation before any live run.
223
+ - **(c) Never run a tagged utterance repeatedly** (the N trials) in live mode
224
+ without opt-in.
225
+
226
+ Read-only data utterances (`side_effects: none`) are safe to run N× live.
227
+
228
+ The runner enforces (b) mechanically: `upgrade-legacy-nga-run-trials.sh` **defaults
229
+ to `simulate`** and passes `--use-live-actions` only when you give it an explicit
230
+ `live` mode arg. Legacy (`--api-name`) has no simulate mode and always runs live, so
231
+ gate side-effecting utterances against legacy upstream (confirm, or hold it to N=1).
232
+
233
+ ## Execution mechanics and traps
234
+
235
+ For each subject × utterance × trial: **start → send → end**, one fresh session
236
+ per trial (independent trials, no cross-turn contamination). This is exactly what
237
+ `scripts/upgrade-legacy-nga-run-trials.sh` does:
238
+
239
+ ```bash
240
+ EVAL_AGENT=<agent> EVAL_ORG=<org-alias> \
241
+ bash scripts/upgrade-legacy-nga-run-trials.sh <legacy|draft> <utt_id> <N> <outdir> "<utterance text>" [simulate|live]
242
+ # mode defaults to `simulate`; pass `live` only for opted-in utterances (gates the
243
+ # draft — legacy has no simulate mode and always runs live)
244
+ ```
245
+
246
+ The reliable per-trial path it runs:
247
+
248
+ ```bash
249
+ # START — capture stdout to a FILE (see trap below); mode flag is start-ONLY
250
+ sf agent preview start --json <SUBJECT_SELECTOR> -o "$ORG" > start.json 2> start.err
251
+ SID=$(python3 -c "import json;print(json.load(open('start.json'))['result']['sessionId'])")
252
+
253
+ # SEND
254
+ sf agent preview send --json <SUBJECT_SELECTOR> --session-id "$SID" \
255
+ -u "$UTTERANCE" -o "$ORG" > send.json 2> send.err
256
+
257
+ # END — frees the session; writes the local plan trace to disk
258
+ sf agent preview end --json <SUBJECT_SELECTOR> --session-id "$SID" -o "$ORG" > end.json 2> end.err
259
+ ```
260
+
261
+ `<SUBJECT_SELECTOR>` is `--api-name <agent>` (legacy) or
262
+ `--authoring-bundle <agent>` (draft). **The mode flag
263
+ `--use-live-actions` / `--simulate-actions` is `start`-ONLY** — mode is fixed at
264
+ session creation. `send`/`end` accept only the subject selector + `--session-id`;
265
+ passing `--use-live-actions` to them fails with
266
+ `Nonexistent flag: --use-live-actions`. Legacy via `--api-name` runs live by
267
+ default and takes no mode flag.
268
+
269
+ ### Traps (baked into the scripts — do not undo them)
270
+
271
+ - **Never pipe preview output through `2>&1 | python`.** The CLI writes a
272
+ progress spinner to stderr; merged into stdout it corrupts the JSON
273
+ (`JSONDecodeError: Expecting value`). Redirect **stdout to a file** and parse
274
+ the file; keep stderr separate. (This is consistent with [SKILL.md](../SKILL.md)
275
+ Rule 1's "always `--json`, don't mangle the data stream".)
276
+ - **Force plain output — `export NO_COLOR=1 FORCE_COLOR=0`.** In some shells/CI,
277
+ `sf … --json` still emits ANSI color codes, and once stdout is redirected to a
278
+ file those escape bytes corrupt the JSON the collector parses. The collector
279
+ script sets both env vars near the top; export them yourself before any manual
280
+ `sf … --json > file` invocation too.
281
+ - **The analyzer locates `.sfdx/agents` by walking up from cwd** (then from
282
+ `<run_dir>`), so it runs from anywhere inside the repo. A fixed cwd would
283
+ report a **false `UNVERIFIED-TRACE`** for both subjects when run from a
284
+ subdirectory — the upward search stays.
285
+ - Always `--json`. Never `jq`/`2>/dev/null` on the data stream itself.
286
+ - Response text lives at `result.messages[*].message`. Also capture
287
+ `isContentSafe`, `planId`, `result[]`, `citedReferences`.
288
+ - Live-action sends can take **30–120 s**. Use a generous timeout (≥ 180 s).
289
+ - Session artifacts land in `.sfdx/agents/<agentIdOrName>/sessions/<sessionId>/`.
290
+ Legacy sessions nest under the **Bot Id** dir (e.g. `0Xx…`); draft sessions
291
+ under the **bundle api-name** dir.
292
+
293
+ ### Captured record (one JSON per trial)
294
+
295
+ `run-trials.sh` writes `<outdir>/<subject>/<utt>/trial-<n>/trial.json`:
296
+
297
+ ```json
298
+ {
299
+ "subject": "legacy|draft",
300
+ "utterance_id": "<utt_id>",
301
+ "trial": 1,
302
+ "sessionId": "…", "planId": "…",
303
+ "response": "…full message text…",
304
+ "isContentSafe": true,
305
+ "result": [], "citedReferences": [],
306
+ "latency_ms": 6731
307
+ }
308
+ ```
309
+
310
+ The `planId` is the join key: the analyzer resolves the plan trace from it.
311
+
312
+ ## Rubric #1 — Trace / action equality (mechanical)
313
+
314
+ The CLI *response* does not expose the plan trace, and `result[]` is empty even
315
+ when an action ran. But **`sf agent preview end` writes a full local plan trace
316
+ to disk, keyed by `planId`** — the authoritative, zero-network, type-agnostic
317
+ source for **both** legacy and NGA:
318
+
319
+ ```text
320
+ .sfdx/agents/<agentId>/sessions/<sessionId>/traces/<planId>.json
321
+ ```
322
+
323
+ `scripts/upgrade-legacy-nga-analyze.py` reads it — this part is **mechanical**
324
+ (objective equality of structured identifiers), so the script does it:
325
+
326
+ ```bash
327
+ EVAL_ORG=<org-alias> \
328
+ python3 scripts/upgrade-legacy-nga-analyze.py <run_dir> <utt_id> [expected_subagent] [expected_actions_csv]
329
+ ```
330
+
331
+ The trace file is a `PlanSuccessResponse` with `topic`/`intent` (the selected
332
+ subagent) and an ordered `plan[]`. The steps that matter:
333
+
334
+ - `FunctionStep.function.{name,input,output}` — each **action call** in order,
335
+ with bound inputs and `output.__action_execution_status__`. Same record shape
336
+ for any action type (Apex / Flow / Prompt / utility) — generic ordered-action
337
+ evidence.
338
+ - **Routing hop:** the NGA draft uses `TransitionStep.data.{from_agent,to_agent}`;
339
+ legacy ReAct uses `UpdateTopicStep` + the top-level `topic` field (no
340
+ `TransitionStep`). The analyzer normalizes both into one
341
+ `Agent Router → <subagent>` row.
342
+
343
+ ### Two trace-shape differences (both handled in the analyzer)
344
+
345
+ 1. **Routing step:** draft = `TransitionStep`; legacy = `UpdateTopicStep` +
346
+ `topic`. The analyzer synthesizes `("Agent Router", topic)` when there is no
347
+ `TransitionStep`.
348
+ 2. **Name suffixes:** legacy `topic`/action names carry a definition-id suffix
349
+ appended to the base name (e.g.
350
+ `Get_All_Loan_Application_Details_179KX000000YehM`); the draft uses the clean
351
+ base name. The suffix format is **not fixed**, so a regex strip is unreliable.
352
+ Instead names match by **substring containment in either direction**
353
+ (`name_match()`, case-insensitive) — two names denote the same entity when one
354
+ contains the other. Names are kept raw in the report; only the match is
355
+ suffix-tolerant.
356
+
357
+ ### Legacy trace needs CLI ≥ 2.149.9
358
+
359
+ The **legacy** trace only populates on `sf` CLI ≥ 2.149.9 (`@salesforce/agents ≥
360
+ 2.0.4`), which fetches it from the v1.1 preview plans endpoint. On older CLIs the
361
+ legacy trace is written as `{}` and `parse_trace()` reports `empty plan ({}) —
362
+ SDK too old`. The draft trace populates on all supported versions. (See
363
+ [Prerequisites](#prerequisites).)
364
+
365
+ ### The oracle triangle — legacy is a BASELINE, not the source of truth
366
+
367
+ Legacy is **not** the pass condition. The legacy agent can itself be defective
368
+ (miss a grounding action, route poorly, leak a value), and a migration that
369
+ *fixes* such a defect must not be flagged as a regression. So Rubric #1 compares
370
+ **three** references and classifies the triangle:
371
+
372
+ | reference | what it is | authority |
373
+ |---|---|---|
374
+ | **spec** | `expected_subagent` / `expected_actions` from the suite, authored from intent | **ORACLE** (intended behavior) |
375
+ | **legacy** | what the old agent actually did (its local trace) | descriptive **baseline** — can be wrong |
376
+ | **draft** | what the NGA under test actually did (its local trace) | **under test** |
377
+
378
+ The analyzer computes a route+action **signature** = `[subagent] + ordered
379
+ actions` for each reference (compared with suffix-tolerant `name_match()`) and
380
+ emits one **triangle verdict**:
381
+
382
+ | legacy vs spec | draft vs spec | verdict | meaning / action |
383
+ |---|---|---|---|
384
+ | match | match | **PASS** | all three agree — nothing to do |
385
+ | match | differ | **DRAFT-REGRESSION** | legacy was right, the draft broke it → fix the draft |
386
+ | differ | match | **PASS + LEGACY-DEFECT** | draft matches intent; legacy was wrong → migration *fixed* a legacy bug |
387
+ | differ | differ (l == d) | **SPEC-REVIEW** | legacy and draft agree with each other but not the spec → spec is likely stale; a human re-confirms intent |
388
+ | differ | differ (l ≠ d) | **ADJUDICATE** | three-way disagreement → hand traces + responses to the LLM judge to decide |
389
+
390
+ If **no spec** is supplied for an utterance, the verdict is **SPEC-UNVERIFIED**:
391
+ the analyzer falls back to the legacy-vs-draft cross-check and notes the judge
392
+ must decide (no oracle to anchor on). An **`inferred`** spec is different — it is
393
+ present, so the triangle *does* fire, but the verdict holds only *pending the
394
+ user's validation*; flag those rows and do not stop the loop while any tested
395
+ utterance is still `inferred` (see
396
+ [Iteration loop and stop condition](#iteration-loop-and-stop-condition)). Supply
397
+ or confirm `expected_*` for every utterance you care about so the triangle can
398
+ anchor on truth.
399
+
400
+ ### Accepted baseline & drift (unintended change across iterations)
401
+
402
+ The spec catches *intended* correctness; a separate **accepted baseline** catches
403
+ *unintended* drift between iterations. The analyzer maintains a JSON file
404
+ (`EVAL_BASELINE`, default `agent-eval/baseline.json`) mapping each utterance to
405
+ the last **human-approved** draft signature:
406
+
407
+ ```json
408
+ { "mortgage_faq": { "subagent": "Financial_Knowledge_Base_Search",
409
+ "actions": ["Get_Financial_Customer_Details","Answer_Financial_FAQs"],
410
+ "approved_at": "…", "approved_from_run": "…" } }
411
+ ```
412
+
413
+ - **Every run** diffs the current draft signature against the recorded baseline
414
+ and reports **Drift: none / DETECTED / no baseline yet**. Drift fires even
415
+ when the draft still matches the spec — it flags *any* change from the last
416
+ approved behavior, catching an accidental regression from an unrelated `.agent`
417
+ edit.
418
+ - **Deliberate re-baseline** is explicit and human-gated: run with `REBASELINE=1`
419
+ to record the current draft signature as the new approved truth and exit
420
+ (writes nothing else). Use it the first time an utterance passes, and again
421
+ whenever the authored intent **intentionally** changes.
422
+ - The baseline stores **clean** draft names (no legacy suffix), and drift is
423
+ compared with `name_match()`, so it is robust to the same suffix noise.
424
+
425
+ Together: the **triangle** answers "is the draft doing the *intended* thing
426
+ (regardless of legacy)?"; **drift** answers "did the draft change from what we
427
+ last approved?". A healthy iteration ends `PASS` (or `PASS + LEGACY-DEFECT`) with
428
+ `Drift: none`.
429
+
430
+ ## Rubric #2 — Response discrepancy (LLM judge)
431
+
432
+ Response comparison is a **semantic judgment and MUST be performed by an LLM**,
433
+ never by regex/heuristics. A scripted approach is actively harmful here: it
434
+ produces false diffs (e.g. tokenizing `617,` in prose ≠ `617`) and cannot judge
435
+ tone, grounding, or spec compliance. It would also force agent/utterance-specific
436
+ vocabulary into the analyzer, which is prohibited.
437
+
438
+ **Mechanism.** The analyzer does **not** score responses. It emits the verbatim
439
+ responses for all N trials (both subjects) followed by a fixed, domain-free
440
+ **analysis prompt** (pre-loaded with the triangle verdict + drift status as
441
+ context). An LLM judge — the agent running the skill, or a dedicated judge
442
+ subagent — reads the responses + the Rubric #1 trace facts and completes it:
443
+
444
+ 1. **Intra-trial consistency** — per subject, are the N trials materially
445
+ equivalent (same facts, acceptable wording variance) or divergent? Pick a
446
+ canonical trial for each side.
447
+ 2. **Data fidelity** — do legacy and draft agree on every concrete fact
448
+ (numbers, amounts, dates, statuses, named entities, IDs)? List any value the
449
+ draft changed, dropped, or added. A factual mismatch is a **REGRESSION**, not
450
+ a style diff.
451
+ 3. **Formatting** — structural differences: bullets/headers/lists, number/money
452
+ formatting, any leaked internal field/action API names.
453
+ 4. **Verbosity & tone** — length, clarity, empathy, appropriate closing offer.
454
+ 5. **Spec compliance** — does each side satisfy the utterance's intent? If the
455
+ action sets differ (e.g. one side grounded via a retrieval action, the other
456
+ answered from model knowledge), judge whether that changes answer
457
+ quality/trustworthiness.
458
+ 6. **Classification** — `EQUIVALENT` | `IMPROVED` | `ACCEPTABLE-DIFF` |
459
+ `REGRESSION`, with a one-line justification and, if not
460
+ `EQUIVALENT`/`IMPROVED`, a concrete recommended `.agent` change.
461
+
462
+ `isContentSafe` (per trial) and the Rubric #1 trace verdicts are the only
463
+ mechanical inputs the judge is handed; everything evaluative is the judge's call.
464
+ Classification meanings:
465
+
466
+ - `EQUIVALENT` — same data, differences immaterial.
467
+ - `IMPROVED` — draft better (clearer/warmer/better formatted/better grounded),
468
+ data intact.
469
+ - `ACCEPTABLE-DIFF` — differs but within tolerance.
470
+ - `REGRESSION` — draft loses/changes data, breaks a policy, is unsafe, or
471
+ routes/acts differently in a way that degrades the answer.
472
+
473
+ ## Trials, caching, and the canonical response
474
+
475
+ - Run `trials` (default 3) per (subject, utterance). Record all N.
476
+ - **Intra-trial variance is an LLM judgment, not a regex diff.** The analyzer
477
+ presents all N verbatim responses per subject; the Rubric #2 judge decides
478
+ whether they are identical / materially equivalent / divergent and picks the
479
+ canonical trial (materially-equivalent set → trial 1; otherwise the
480
+ representative/modal variant, flagging `HIGH-VARIANCE`). Do **not** extract
481
+ "facts" with hardcoded field labels or token regexes — it is agent-specific
482
+ (prohibited) and produces false diffs.
483
+ - **Legacy caching:** legacy is frozen, so cache its per-trial results and reuse
484
+ across draft edits. Cache key =
485
+ `sha256(legacy_api_name + active_BotVersionId + utterance_text + trial_index)`.
486
+ Store `active_BotVersionId` in cache metadata and **invalidate** if it changes
487
+ (legacy got re-published). `--refresh-legacy` forces a re-run.
488
+ - **Draft results are never cached** — re-collect them on every iteration
489
+ because the `.agent` file changes.
490
+
491
+ Three separate artifacts, three separate concerns — do not conflate them: the
492
+ **legacy cache** (don't re-run frozen legacy), the **accepted baseline**
493
+ (draft-over-time drift), and the **spec** (intent).
494
+
495
+ ## The report
496
+
497
+ The analyzer writes `<run_dir>/report.md` (and prints it): the mechanical part +
498
+ the raw responses + the Rubric #2 prompt. The LLM judge's completed analysis is
499
+ appended (or captured alongside), as is the spec-validation block below — both are
500
+ skill/judge-supplied, since the mechanical analyzer has no `spec_status` notion (it
501
+ receives only `expected_*` as arguments).
502
+
503
+ 1. **Header** — org, run id, `trials`, per-trial latency, per-trial
504
+ `isContentSafe`, per-trial word count, legacy/draft planIds.
505
+ 2. **Spec validation (inferred specs)** — every utterance whose `spec_status` is
506
+ `inferred`, each with its `text` and the skill's **proposed** `expected_subagent`
507
+ + `expected_actions` plus a one-line note on the intent they were inferred from
508
+ (the utterance + the agent's topic/action catalog — never copied from legacy).
509
+ The user confirms or corrects them in one pass; on confirm, flip the entry to
510
+ `confirmed` (and `REBASELINE` it the first time it passes — see
511
+ [drift](#accepted-baseline--drift-unintended-change-across-iterations)). This
512
+ block comes **before** Rubric #1 because any triangle verdict for an `inferred`
513
+ row is provisional until its spec is confirmed; the run cannot be declared done
514
+ while the block is non-empty (see
515
+ [stop condition](#iteration-loop-and-stop-condition)). When every spec is
516
+ already `confirmed` the block is empty and the report says so.
517
+ 3. **Rubric #1 (mechanical)** — per-subject trace table
518
+ (subagent / ordered actions / verdict) + legacy-vs-draft cross-check + oracle
519
+ triangle + drift + optional draft action-input binding.
520
+ 4. **Responses (verbatim)** — all N trials for both subjects.
521
+ 5. **Rubric #2 (LLM judge)** — the analysis prompt and the judge's completed
522
+ answer.
523
+ 6. **Actionable diffs** — consolidated proposed `.agent` edits, each linked to
524
+ the utterance(s) that motivated it.
525
+
526
+ ## Iteration loop and stop condition
527
+
528
+ ```text
529
+ compile draft (index-agent.mjs) ──► collect draft trials (N×)
530
+ ▲ │
531
+ │ ▼
532
+ edit .agent ◄── findings ◄── report ◄── compare vs cached legacy trials
533
+ ```
534
+
535
+ **Stop when** every utterance's **triangle verdict** is `PASS` or
536
+ `PASS + LEGACY-DEFECT` (no open `DRAFT-REGRESSION`; any `SPEC-REVIEW` /
537
+ `ADJUDICATE` resolved by a human/judge decision, spec updated if it was stale),
538
+ **every tested utterance's `spec_status` is `confirmed`** (no `inferred` spec still
539
+ awaiting the user's validation), **drift** is `none` against a
540
+ deliberately-approved baseline, and Rubric #2 is `EQUIVALENT` / `IMPROVED` (no open
541
+ `REGRESSION`). A `LEGACY-DEFECT` is a **pass** —
542
+ do not chase legacy parity when legacy was the one that was wrong.
543
+
544
+ **Draft-only throughout: no publish/activate without explicit human approval.**
545
+ Deploy the draft bundle (`sf project deploy start`) only if a preview needs it to
546
+ pick up on-disk edits — confirm once whether an `--authoring-bundle` preview
547
+ reflects the `.agent` immediately, and skip the deploy if it does.