@salesforce/afv-skills 1.22.0 → 1.24.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 (1675) hide show
  1. package/package.json +1 -1
  2. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/SKILL.md +7 -7
  3. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/references/README.md +7 -7
  4. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/references/quick-reference.md +2 -2
  5. package/skills/{getting-datacloud-schema → data360-schema-get}/SKILL.md +26 -26
  6. package/skills/{getting-datacloud-schema → data360-schema-get}/references/README.md +9 -9
  7. package/skills/activating-datacloud/README.md +0 -39
  8. package/skills/activating-datacloud/SKILL.md +0 -117
  9. package/skills/analyzing-omnistudio-dependencies/CREDITS.md +0 -5
  10. package/skills/analyzing-omnistudio-dependencies/SKILL.md +0 -476
  11. package/skills/analyzing-omnistudio-dependencies/references/dependency-patterns.md +0 -508
  12. package/skills/analyzing-omnistudio-dependencies/references/namespace-guide.md +0 -300
  13. package/skills/applying-cms-brand/SKILL.md +0 -170
  14. package/skills/applying-slds/SKILL.md +0 -322
  15. package/skills/applying-slds/checklists.md +0 -83
  16. package/skills/applying-slds/examples.md +0 -283
  17. package/skills/applying-slds/guidance/README.md +0 -83
  18. package/skills/applying-slds/guidance/blueprints-index.md +0 -213
  19. package/skills/applying-slds/guidance/icons-guidance.md +0 -186
  20. package/skills/applying-slds/guidance/overviews/borders.md +0 -236
  21. package/skills/applying-slds/guidance/overviews/color.md +0 -266
  22. package/skills/applying-slds/guidance/overviews/display-density.md +0 -366
  23. package/skills/applying-slds/guidance/overviews/icons.md +0 -240
  24. package/skills/applying-slds/guidance/overviews/illustrations.md +0 -235
  25. package/skills/applying-slds/guidance/overviews/shadows.md +0 -176
  26. package/skills/applying-slds/guidance/overviews/spacing.md +0 -216
  27. package/skills/applying-slds/guidance/overviews/typography.md +0 -323
  28. package/skills/applying-slds/guidance/overviews/utilities.md +0 -542
  29. package/skills/applying-slds/guidance/slds-development-guide.md +0 -288
  30. package/skills/applying-slds/guidance/styling-hooks/borders.md +0 -202
  31. package/skills/applying-slds/guidance/styling-hooks/color/expressive-palette-hooks.md +0 -153
  32. package/skills/applying-slds/guidance/styling-hooks/color/index.md +0 -171
  33. package/skills/applying-slds/guidance/styling-hooks/color/semantic/accent-hooks.md +0 -204
  34. package/skills/applying-slds/guidance/styling-hooks/color/semantic/feedback-hooks.md +0 -768
  35. package/skills/applying-slds/guidance/styling-hooks/color/semantic/surface-hooks.md +0 -337
  36. package/skills/applying-slds/guidance/styling-hooks/color/system-hooks.md +0 -132
  37. package/skills/applying-slds/guidance/styling-hooks/index.md +0 -327
  38. package/skills/applying-slds/guidance/styling-hooks/shadows.md +0 -238
  39. package/skills/applying-slds/guidance/styling-hooks/spacing.md +0 -254
  40. package/skills/applying-slds/guidance/styling-hooks/typography.md +0 -448
  41. package/skills/applying-slds/guidance/utilities/alignment.md +0 -119
  42. package/skills/applying-slds/guidance/utilities/borders.md +0 -131
  43. package/skills/applying-slds/guidance/utilities/box.md +0 -125
  44. package/skills/applying-slds/guidance/utilities/color.md +0 -165
  45. package/skills/applying-slds/guidance/utilities/dark-mode.md +0 -111
  46. package/skills/applying-slds/guidance/utilities/description-list.md +0 -168
  47. package/skills/applying-slds/guidance/utilities/floats.md +0 -117
  48. package/skills/applying-slds/guidance/utilities/grid.md +0 -264
  49. package/skills/applying-slds/guidance/utilities/horizontal-list.md +0 -110
  50. package/skills/applying-slds/guidance/utilities/hyphenation.md +0 -84
  51. package/skills/applying-slds/guidance/utilities/index.md +0 -205
  52. package/skills/applying-slds/guidance/utilities/interactions.md +0 -89
  53. package/skills/applying-slds/guidance/utilities/layout.md +0 -109
  54. package/skills/applying-slds/guidance/utilities/line-clamp.md +0 -131
  55. package/skills/applying-slds/guidance/utilities/margin.md +0 -155
  56. package/skills/applying-slds/guidance/utilities/media-object.md +0 -161
  57. package/skills/applying-slds/guidance/utilities/name-value-list.md +0 -152
  58. package/skills/applying-slds/guidance/utilities/padding.md +0 -155
  59. package/skills/applying-slds/guidance/utilities/position.md +0 -177
  60. package/skills/applying-slds/guidance/utilities/print.md +0 -114
  61. package/skills/applying-slds/guidance/utilities/scrollable.md +0 -126
  62. package/skills/applying-slds/guidance/utilities/sizing.md +0 -190
  63. package/skills/applying-slds/guidance/utilities/themes.md +0 -121
  64. package/skills/applying-slds/guidance/utilities/truncate.md +0 -127
  65. package/skills/applying-slds/guidance/utilities/typography.md +0 -166
  66. package/skills/applying-slds/guidance/utilities/vertical-list.md +0 -166
  67. package/skills/applying-slds/guidance/utilities/visibility.md +0 -228
  68. package/skills/applying-slds/metadata/README.md +0 -84
  69. package/skills/applying-slds/metadata/blueprints/components/accordion.yaml +0 -304
  70. package/skills/applying-slds/metadata/blueprints/components/activity-timeline.yaml +0 -92
  71. package/skills/applying-slds/metadata/blueprints/components/alert.yaml +0 -103
  72. package/skills/applying-slds/metadata/blueprints/components/app-launcher.yaml +0 -94
  73. package/skills/applying-slds/metadata/blueprints/components/avatar-group.yaml +0 -81
  74. package/skills/applying-slds/metadata/blueprints/components/avatar.yaml +0 -97
  75. package/skills/applying-slds/metadata/blueprints/components/badges.yaml +0 -102
  76. package/skills/applying-slds/metadata/blueprints/components/brand-band.yaml +0 -198
  77. package/skills/applying-slds/metadata/blueprints/components/breadcrumbs.yaml +0 -95
  78. package/skills/applying-slds/metadata/blueprints/components/builder-header.yaml +0 -192
  79. package/skills/applying-slds/metadata/blueprints/components/button-groups.yaml +0 -82
  80. package/skills/applying-slds/metadata/blueprints/components/button-icons.yaml +0 -295
  81. package/skills/applying-slds/metadata/blueprints/components/buttons.yaml +0 -230
  82. package/skills/applying-slds/metadata/blueprints/components/cards.yaml +0 -124
  83. package/skills/applying-slds/metadata/blueprints/components/carousel.yaml +0 -140
  84. package/skills/applying-slds/metadata/blueprints/components/chat.yaml +0 -179
  85. package/skills/applying-slds/metadata/blueprints/components/checkbox-button-group.yaml +0 -192
  86. package/skills/applying-slds/metadata/blueprints/components/checkbox-button.yaml +0 -204
  87. package/skills/applying-slds/metadata/blueprints/components/checkbox-toggle.yaml +0 -177
  88. package/skills/applying-slds/metadata/blueprints/components/checkbox.yaml +0 -108
  89. package/skills/applying-slds/metadata/blueprints/components/color-picker.yaml +0 -172
  90. package/skills/applying-slds/metadata/blueprints/components/combobox.yaml +0 -136
  91. package/skills/applying-slds/metadata/blueprints/components/counter.yaml +0 -147
  92. package/skills/applying-slds/metadata/blueprints/components/data-tables.yaml +0 -157
  93. package/skills/applying-slds/metadata/blueprints/components/datepickers.yaml +0 -130
  94. package/skills/applying-slds/metadata/blueprints/components/datetime-picker.yaml +0 -155
  95. package/skills/applying-slds/metadata/blueprints/components/docked-composer.yaml +0 -201
  96. package/skills/applying-slds/metadata/blueprints/components/docked-form-footer.yaml +0 -161
  97. package/skills/applying-slds/metadata/blueprints/components/docked-utility-bar.yaml +0 -175
  98. package/skills/applying-slds/metadata/blueprints/components/drop-zone.yaml +0 -115
  99. package/skills/applying-slds/metadata/blueprints/components/dueling-picklist.yaml +0 -196
  100. package/skills/applying-slds/metadata/blueprints/components/dynamic-icons.yaml +0 -128
  101. package/skills/applying-slds/metadata/blueprints/components/dynamic-menu.yaml +0 -141
  102. package/skills/applying-slds/metadata/blueprints/components/expandable-section.yaml +0 -115
  103. package/skills/applying-slds/metadata/blueprints/components/expression.yaml +0 -143
  104. package/skills/applying-slds/metadata/blueprints/components/feeds.yaml +0 -125
  105. package/skills/applying-slds/metadata/blueprints/components/file-selector.yaml +0 -154
  106. package/skills/applying-slds/metadata/blueprints/components/files.yaml +0 -119
  107. package/skills/applying-slds/metadata/blueprints/components/form-element.yaml +0 -145
  108. package/skills/applying-slds/metadata/blueprints/components/global-header.yaml +0 -120
  109. package/skills/applying-slds/metadata/blueprints/components/global-navigation.yaml +0 -100
  110. package/skills/applying-slds/metadata/blueprints/components/icons.yaml +0 -138
  111. package/skills/applying-slds/metadata/blueprints/components/illustration.yaml +0 -205
  112. package/skills/applying-slds/metadata/blueprints/components/input.yaml +0 -151
  113. package/skills/applying-slds/metadata/blueprints/components/list-builder.yaml +0 -127
  114. package/skills/applying-slds/metadata/blueprints/components/lookups.yaml +0 -132
  115. package/skills/applying-slds/metadata/blueprints/components/map.yaml +0 -118
  116. package/skills/applying-slds/metadata/blueprints/components/menus.yaml +0 -134
  117. package/skills/applying-slds/metadata/blueprints/components/modals.yaml +0 -152
  118. package/skills/applying-slds/metadata/blueprints/components/notifications.yaml +0 -88
  119. package/skills/applying-slds/metadata/blueprints/components/page-headers.yaml +0 -135
  120. package/skills/applying-slds/metadata/blueprints/components/panels.yaml +0 -149
  121. package/skills/applying-slds/metadata/blueprints/components/path.yaml +0 -154
  122. package/skills/applying-slds/metadata/blueprints/components/picklist.yaml +0 -125
  123. package/skills/applying-slds/metadata/blueprints/components/pills.yaml +0 -154
  124. package/skills/applying-slds/metadata/blueprints/components/popovers.yaml +0 -120
  125. package/skills/applying-slds/metadata/blueprints/components/progress-bar.yaml +0 -110
  126. package/skills/applying-slds/metadata/blueprints/components/progress-indicator.yaml +0 -133
  127. package/skills/applying-slds/metadata/blueprints/components/progress-ring.yaml +0 -102
  128. package/skills/applying-slds/metadata/blueprints/components/prompt.yaml +0 -126
  129. package/skills/applying-slds/metadata/blueprints/components/publishers.yaml +0 -178
  130. package/skills/applying-slds/metadata/blueprints/components/radio-button-group.yaml +0 -172
  131. package/skills/applying-slds/metadata/blueprints/components/radio-group.yaml +0 -112
  132. package/skills/applying-slds/metadata/blueprints/components/rich-text-editor.yaml +0 -135
  133. package/skills/applying-slds/metadata/blueprints/components/scoped-notifications.yaml +0 -188
  134. package/skills/applying-slds/metadata/blueprints/components/scoped-tabs.yaml +0 -97
  135. package/skills/applying-slds/metadata/blueprints/components/select.yaml +0 -127
  136. package/skills/applying-slds/metadata/blueprints/components/setup-assistant.yaml +0 -152
  137. package/skills/applying-slds/metadata/blueprints/components/slider.yaml +0 -111
  138. package/skills/applying-slds/metadata/blueprints/components/spinners.yaml +0 -135
  139. package/skills/applying-slds/metadata/blueprints/components/split-view.yaml +0 -112
  140. package/skills/applying-slds/metadata/blueprints/components/summary-detail.yaml +0 -103
  141. package/skills/applying-slds/metadata/blueprints/components/tabs.yaml +0 -138
  142. package/skills/applying-slds/metadata/blueprints/components/textarea.yaml +0 -116
  143. package/skills/applying-slds/metadata/blueprints/components/tiles.yaml +0 -108
  144. package/skills/applying-slds/metadata/blueprints/components/timepicker.yaml +0 -111
  145. package/skills/applying-slds/metadata/blueprints/components/toast.yaml +0 -154
  146. package/skills/applying-slds/metadata/blueprints/components/tooltips.yaml +0 -107
  147. package/skills/applying-slds/metadata/blueprints/components/tree-grid.yaml +0 -116
  148. package/skills/applying-slds/metadata/blueprints/components/trees.yaml +0 -116
  149. package/skills/applying-slds/metadata/blueprints/components/trial-bar.yaml +0 -112
  150. package/skills/applying-slds/metadata/blueprints/components/vertical-navigation.yaml +0 -130
  151. package/skills/applying-slds/metadata/blueprints/components/vertical-tabs.yaml +0 -140
  152. package/skills/applying-slds/metadata/blueprints/components/visual-picker.yaml +0 -150
  153. package/skills/applying-slds/metadata/blueprints/components/welcome-mat.yaml +0 -136
  154. package/skills/applying-slds/metadata/hooks-index.json +0 -6272
  155. package/skills/applying-slds/metadata/icon-metadata.json +0 -38466
  156. package/skills/applying-slds/metadata/utilities-index.json +0 -21912
  157. package/skills/applying-slds/references/component-selection.md +0 -112
  158. package/skills/applying-slds/references/icons-decision-guide.md +0 -124
  159. package/skills/applying-slds/references/styling-decision-guide.md +0 -228
  160. package/skills/applying-slds/references/utilities-quick-ref.md +0 -125
  161. package/skills/applying-slds/scripts/search-blueprints.cjs +0 -117
  162. package/skills/applying-slds/scripts/search-hooks.cjs +0 -139
  163. package/skills/applying-slds/scripts/search-icons.cjs +0 -174
  164. package/skills/applying-slds/scripts/search-utilities.cjs +0 -161
  165. package/skills/building-mobile-apps/SKILL.md +0 -69
  166. package/skills/building-omnistudio-callable-apex/CREDITS.md +0 -9
  167. package/skills/building-omnistudio-callable-apex/README.md +0 -80
  168. package/skills/building-omnistudio-callable-apex/SKILL.md +0 -275
  169. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_openinterface.cls +0 -40
  170. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_vanilla.cls +0 -32
  171. package/skills/building-omnistudio-callable-apex/assets/pattern_migration.cls +0 -54
  172. package/skills/building-omnistudio-callable-apex/assets/pattern_openinterface.cls +0 -45
  173. package/skills/building-omnistudio-callable-apex/assets/pattern_test_class.cls +0 -65
  174. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/IndustriesCallableException.cls +0 -7
  175. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.cls +0 -115
  176. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallableTest.cls +0 -189
  177. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/TRANSCRIPT.md +0 -115
  178. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.cls +0 -7
  179. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallable.cls +0 -74
  180. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallableTest.cls +0 -146
  181. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomRemoteClass.cls +0 -16
  182. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md +0 -120
  183. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.cls +0 -7
  184. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallable.cls +0 -73
  185. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallableTest.cls +0 -128
  186. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomVlocityOpenInterface2.cls +0 -23
  187. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md +0 -75
  188. package/skills/building-omnistudio-datamapper/CREDITS.md +0 -5
  189. package/skills/building-omnistudio-datamapper/SKILL.md +0 -269
  190. package/skills/building-omnistudio-datamapper/assets/completion-summary-template.md +0 -28
  191. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-extract.json +0 -6
  192. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-item.json +0 -12
  193. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-load.json +0 -6
  194. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-transform.json +0 -6
  195. package/skills/building-omnistudio-datamapper/references/best-practices.md +0 -277
  196. package/skills/building-omnistudio-datamapper/references/naming-conventions.md +0 -145
  197. package/skills/building-omnistudio-flexcard/CREDITS.md +0 -5
  198. package/skills/building-omnistudio-flexcard/SKILL.md +0 -324
  199. package/skills/building-omnistudio-flexcard/assets/omni-ui-card.json +0 -10
  200. package/skills/building-omnistudio-flexcard/references/best-practices.md +0 -291
  201. package/skills/building-omnistudio-flexcard/references/data-binding-guide.md +0 -311
  202. package/skills/building-omnistudio-flexcard/references/scoring-rubric.md +0 -66
  203. package/skills/building-omnistudio-flexcard/scripts/flexcard-commands.sh +0 -24
  204. package/skills/building-omnistudio-integration-procedure/CREDITS.md +0 -5
  205. package/skills/building-omnistudio-integration-procedure/SKILL.md +0 -274
  206. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-dr-extract.json +0 -10
  207. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-set-values.json +0 -10
  208. package/skills/building-omnistudio-integration-procedure/assets/omni-process-ip.json +0 -12
  209. package/skills/building-omnistudio-integration-procedure/assets/scoring-report-format.txt +0 -14
  210. package/skills/building-omnistudio-integration-procedure/references/best-practices.md +0 -388
  211. package/skills/building-omnistudio-integration-procedure/references/element-types.md +0 -588
  212. package/skills/building-omnistudio-integration-procedure/scripts/cli-commands.sh +0 -18
  213. package/skills/building-omnistudio-omniscript/CREDITS.md +0 -5
  214. package/skills/building-omnistudio-omniscript/SKILL.md +0 -366
  215. package/skills/building-omnistudio-omniscript/assets/omni-process-element-step.json +0 -10
  216. package/skills/building-omnistudio-omniscript/assets/omni-process-element-text-block.json +0 -11
  217. package/skills/building-omnistudio-omniscript/assets/omni-process-omniscript.json +0 -12
  218. package/skills/building-omnistudio-omniscript/references/best-practices.md +0 -480
  219. package/skills/building-omnistudio-omniscript/references/element-types.md +0 -1172
  220. package/skills/building-omnistudio-omniscript/scripts/check-duplicate-omniscript.sh +0 -13
  221. package/skills/building-omnistudio-omniscript/scripts/cli-reference.sh +0 -21
  222. package/skills/building-omnistudio-omniscript/scripts/deploy-omniscript.sh +0 -29
  223. package/skills/building-sf-integrations/CREDITS.md +0 -5
  224. package/skills/building-sf-integrations/README.md +0 -95
  225. package/skills/building-sf-integrations/SKILL.md +0 -191
  226. package/skills/building-sf-integrations/assets/callouts/callout-retry-handler.cls +0 -167
  227. package/skills/building-sf-integrations/assets/callouts/http-response-handler.cls +0 -257
  228. package/skills/building-sf-integrations/assets/callouts/rest-queueable-callout.cls +0 -262
  229. package/skills/building-sf-integrations/assets/callouts/rest-sync-callout.cls +0 -211
  230. package/skills/building-sf-integrations/assets/cdc/cdc-handler.cls +0 -246
  231. package/skills/building-sf-integrations/assets/cdc/cdc-subscriber-trigger.trigger +0 -139
  232. package/skills/building-sf-integrations/assets/endpoint-security/example.cspTrustedSite-meta.xml +0 -58
  233. package/skills/building-sf-integrations/assets/endpoint-security/example.remoteSite-meta.xml +0 -39
  234. package/skills/building-sf-integrations/assets/external-credentials/jwt-external-credential.externalCredential-meta.xml +0 -90
  235. package/skills/building-sf-integrations/assets/external-credentials/oauth-external-credential.externalCredential-meta.xml +0 -87
  236. package/skills/building-sf-integrations/assets/external-services/external-service-operations.md +0 -221
  237. package/skills/building-sf-integrations/assets/external-services/openapi-registration.externalServiceRegistration-meta.xml +0 -193
  238. package/skills/building-sf-integrations/assets/named-credentials/certificate-auth.namedCredential-meta.xml +0 -62
  239. package/skills/building-sf-integrations/assets/named-credentials/custom-auth.namedCredential-meta.xml +0 -71
  240. package/skills/building-sf-integrations/assets/named-credentials/oauth-client-credentials.namedCredential-meta.xml +0 -51
  241. package/skills/building-sf-integrations/assets/named-credentials/oauth-jwt-bearer.namedCredential-meta.xml +0 -67
  242. package/skills/building-sf-integrations/assets/platform-events/event-publisher.cls +0 -191
  243. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-action.cls +0 -295
  244. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-trigger.trigger +0 -108
  245. package/skills/building-sf-integrations/assets/platform-events/platform-event-definition.object-meta.xml +0 -124
  246. package/skills/building-sf-integrations/assets/soap/soap-callout-service.cls +0 -186
  247. package/skills/building-sf-integrations/assets/soap/wsdl2apex-guide.md +0 -213
  248. package/skills/building-sf-integrations/hooks/scripts/suggest_credential_setup.py +0 -271
  249. package/skills/building-sf-integrations/hooks/scripts/validate_integration.py +0 -363
  250. package/skills/building-sf-integrations/references/callout-patterns.md +0 -719
  251. package/skills/building-sf-integrations/references/cdc-guide.md +0 -288
  252. package/skills/building-sf-integrations/references/cli-reference.md +0 -94
  253. package/skills/building-sf-integrations/references/event-driven-architecture-guide.md +0 -266
  254. package/skills/building-sf-integrations/references/event-patterns.md +0 -838
  255. package/skills/building-sf-integrations/references/external-services-guide.md +0 -303
  256. package/skills/building-sf-integrations/references/messaging-api-v2.md +0 -609
  257. package/skills/building-sf-integrations/references/named-credentials-automation.md +0 -201
  258. package/skills/building-sf-integrations/references/named-credentials-guide.md +0 -173
  259. package/skills/building-sf-integrations/references/platform-events-guide.md +0 -288
  260. package/skills/building-sf-integrations/references/rest-callout-patterns.md +0 -288
  261. package/skills/building-sf-integrations/references/scoring-rubric.md +0 -59
  262. package/skills/building-sf-integrations/references/security-best-practices.md +0 -248
  263. package/skills/building-sf-integrations/scripts/README.md +0 -100
  264. package/skills/building-sf-integrations/scripts/configure-named-credential.sh +0 -236
  265. package/skills/building-sf-integrations/scripts/set-api-credential.sh +0 -146
  266. package/skills/building-sf-integrations/scripts/templates/setup-credentials-with-csp.sh +0 -158
  267. package/skills/building-ui-bundle-app/SKILL.md +0 -350
  268. package/skills/building-ui-bundle-frontend/SKILL.md +0 -135
  269. package/skills/building-ui-bundle-frontend/implementation/component.md +0 -78
  270. package/skills/building-ui-bundle-frontend/implementation/header-footer.md +0 -132
  271. package/skills/building-ui-bundle-frontend/implementation/page.md +0 -93
  272. package/skills/configuring-code-analyzer/SKILL.md +0 -482
  273. package/skills/configuring-code-analyzer/examples/apex-project-config.yml +0 -41
  274. package/skills/configuring-code-analyzer/examples/ci-github-actions.yml +0 -96
  275. package/skills/configuring-code-analyzer/examples/fullstack-project-config.yml +0 -46
  276. package/skills/configuring-code-analyzer/examples/lwc-project-config.yml +0 -26
  277. package/skills/configuring-code-analyzer/references/ci-cd-templates.md +0 -648
  278. package/skills/configuring-code-analyzer/references/config-schema.md +0 -257
  279. package/skills/configuring-code-analyzer/references/diagnostic-flow.md +0 -70
  280. package/skills/configuring-code-analyzer/references/engine-prerequisites.md +0 -276
  281. package/skills/configuring-code-analyzer/references/rule-name-resolution.md +0 -67
  282. package/skills/configuring-code-analyzer/references/troubleshooting.md +0 -298
  283. package/skills/configuring-code-analyzer/scripts/check-prerequisites.sh +0 -189
  284. package/skills/configuring-code-analyzer/scripts/generate-config.sh +0 -143
  285. package/skills/configuring-code-analyzer/scripts/validate-config.sh +0 -153
  286. package/skills/configuring-connected-apps/CREDITS.md +0 -3
  287. package/skills/configuring-connected-apps/README.md +0 -99
  288. package/skills/configuring-connected-apps/SKILL.md +0 -223
  289. package/skills/configuring-connected-apps/assets/connected-app-basic.xml +0 -29
  290. package/skills/configuring-connected-apps/assets/connected-app-canvas.xml +0 -62
  291. package/skills/configuring-connected-apps/assets/connected-app-jwt.xml +0 -49
  292. package/skills/configuring-connected-apps/assets/connected-app-oauth.xml +0 -65
  293. package/skills/configuring-connected-apps/assets/eca-global-oauth.xml +0 -36
  294. package/skills/configuring-connected-apps/assets/eca-oauth-settings.xml +0 -36
  295. package/skills/configuring-connected-apps/assets/eca-policies.xml +0 -36
  296. package/skills/configuring-connected-apps/assets/external-client-app.xml +0 -35
  297. package/skills/configuring-connected-apps/references/example-usage.md +0 -256
  298. package/skills/configuring-connected-apps/references/migration-guide.md +0 -328
  299. package/skills/configuring-connected-apps/references/oauth-flows-reference.md +0 -660
  300. package/skills/configuring-connected-apps/references/security-checklist.md +0 -209
  301. package/skills/configuring-connected-apps/references/testing-validation-guide.md +0 -275
  302. package/skills/connecting-datacloud/CREDITS.md +0 -5
  303. package/skills/connecting-datacloud/README.md +0 -59
  304. package/skills/connecting-datacloud/SKILL.md +0 -154
  305. package/skills/connecting-datacloud/examples/connections/heroku-postgres.json +0 -15
  306. package/skills/connecting-datacloud/examples/connections/ingest-api-connection.json +0 -5
  307. package/skills/connecting-datacloud/examples/connections/ingest-api-schema.json +0 -31
  308. package/skills/connecting-datacloud/examples/connections/redshift.json +0 -16
  309. package/skills/connecting-datacloud/examples/connections/sharepoint-unstructured.json +0 -20
  310. package/skills/connecting-datacloud/examples/connections/snowflake-connection.json +0 -42
  311. package/skills/creating-b2b-commerce-store/SKILL.md +0 -167
  312. package/skills/creating-b2b-commerce-store/references/store-vs-storefront.md +0 -169
  313. package/skills/debugging-apex-logs/CREDITS.md +0 -22
  314. package/skills/debugging-apex-logs/README.md +0 -74
  315. package/skills/debugging-apex-logs/SKILL.md +0 -171
  316. package/skills/debugging-apex-logs/assets/benchmarking-template.cls +0 -327
  317. package/skills/debugging-apex-logs/assets/cpu-heap-optimization.cls +0 -307
  318. package/skills/debugging-apex-logs/assets/dml-in-loop-fix.cls +0 -219
  319. package/skills/debugging-apex-logs/assets/null-pointer-fix.cls +0 -252
  320. package/skills/debugging-apex-logs/assets/soql-in-loop-fix.cls +0 -157
  321. package/skills/debugging-apex-logs/references/analysis-playbook.md +0 -53
  322. package/skills/debugging-apex-logs/references/benchmarking-guide.md +0 -287
  323. package/skills/debugging-apex-logs/references/cli-commands.md +0 -368
  324. package/skills/debugging-apex-logs/references/common-issues.md +0 -68
  325. package/skills/debugging-apex-logs/references/debug-log-reference.md +0 -328
  326. package/skills/debugging-apex-logs/references/log-analysis-tools.md +0 -248
  327. package/skills/debugging-apex-logs/references/scoring-rubric.md +0 -21
  328. package/skills/deploying-metadata/CREDITS.md +0 -25
  329. package/skills/deploying-metadata/README.md +0 -104
  330. package/skills/deploying-metadata/SKILL.md +0 -213
  331. package/skills/deploying-metadata/assets/destructiveChanges.xml +0 -143
  332. package/skills/deploying-metadata/assets/package.xml +0 -121
  333. package/skills/deploying-metadata/references/agent-deployment-guide.md +0 -628
  334. package/skills/deploying-metadata/references/deploy.sh +0 -73
  335. package/skills/deploying-metadata/references/deployment-report-template.md +0 -89
  336. package/skills/deploying-metadata/references/deployment-workflows.md +0 -395
  337. package/skills/deploying-metadata/references/orchestration.md +0 -183
  338. package/skills/deploying-metadata/references/trigger-deployment-safety.md +0 -376
  339. package/skills/deploying-omnistudio-datapacks/CREDITS.md +0 -5
  340. package/skills/deploying-omnistudio-datapacks/README.md +0 -88
  341. package/skills/deploying-omnistudio-datapacks/SKILL.md +0 -173
  342. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/TRANSCRIPT.md +0 -124
  343. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/deploy-business-internet-plus-bundle.yaml +0 -11
  344. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/TRANSCRIPT.md +0 -142
  345. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/deploy-business-internet-plus-bundle.yaml +0 -10
  346. package/skills/deploying-omnistudio-datapacks/references/job-file-template.md +0 -42
  347. package/skills/deploying-omnistudio-datapacks/references/troubleshooting-matrix.md +0 -24
  348. package/skills/deploying-ui-bundle/SKILL.md +0 -79
  349. package/skills/developing-agentforce/README.md +0 -112
  350. package/skills/developing-agentforce/SKILL.md +0 -518
  351. package/skills/developing-agentforce/assets/README-legacy.md +0 -89
  352. package/skills/developing-agentforce/assets/agent-spec-template.md +0 -90
  353. package/skills/developing-agentforce/assets/agents/README.md +0 -45
  354. package/skills/developing-agentforce/assets/agents/hello-world.agent +0 -60
  355. package/skills/developing-agentforce/assets/agents/multi-subagent.agent +0 -105
  356. package/skills/developing-agentforce/assets/agents/order-service.agent +0 -272
  357. package/skills/developing-agentforce/assets/agents/production-faq.agent +0 -101
  358. package/skills/developing-agentforce/assets/agents/production-faq.bundle-meta.xml +0 -4
  359. package/skills/developing-agentforce/assets/agents/simple-qa.agent +0 -72
  360. package/skills/developing-agentforce/assets/agents/verification-gate.agent +0 -280
  361. package/skills/developing-agentforce/assets/apex/models-api-queueable.cls +0 -225
  362. package/skills/developing-agentforce/assets/bundle-meta.xml +0 -23
  363. package/skills/developing-agentforce/assets/components/apex-action.agent +0 -52
  364. package/skills/developing-agentforce/assets/components/error-handling.agent +0 -58
  365. package/skills/developing-agentforce/assets/components/escalation-setup.agent +0 -169
  366. package/skills/developing-agentforce/assets/components/flow-action.agent +0 -66
  367. package/skills/developing-agentforce/assets/components/n-ary-conditions.agent +0 -110
  368. package/skills/developing-agentforce/assets/components/subagent-with-actions.agent +0 -40
  369. package/skills/developing-agentforce/assets/deterministic-routing.agent +0 -166
  370. package/skills/developing-agentforce/assets/escalation-pattern.agent +0 -209
  371. package/skills/developing-agentforce/assets/flow-action-lookup.agent +0 -115
  372. package/skills/developing-agentforce/assets/hub-and-spoke.agent +0 -104
  373. package/skills/developing-agentforce/assets/invocable-apex-template.cls +0 -187
  374. package/skills/developing-agentforce/assets/local-info-agent-annotated.agent +0 -355
  375. package/skills/developing-agentforce/assets/metadata/basic-prompt-template.promptTemplate-meta.xml +0 -109
  376. package/skills/developing-agentforce/assets/metadata/genai-function-apex.xml +0 -92
  377. package/skills/developing-agentforce/assets/metadata/genai-function-flow.xml +0 -57
  378. package/skills/developing-agentforce/assets/metadata/genai-plugin.xml +0 -72
  379. package/skills/developing-agentforce/assets/metadata/http-callout-flow.flow-meta.xml +0 -348
  380. package/skills/developing-agentforce/assets/metadata/record-grounded-prompt.promptTemplate-meta.xml +0 -136
  381. package/skills/developing-agentforce/assets/minimal-starter.agent +0 -42
  382. package/skills/developing-agentforce/assets/patterns/README.md +0 -254
  383. package/skills/developing-agentforce/assets/patterns/action-callbacks.agent +0 -178
  384. package/skills/developing-agentforce/assets/patterns/advanced-input-bindings.agent +0 -141
  385. package/skills/developing-agentforce/assets/patterns/bidirectional-routing.agent +0 -156
  386. package/skills/developing-agentforce/assets/patterns/critical-input-collection.agent +0 -244
  387. package/skills/developing-agentforce/assets/patterns/delegation-routing.agent +0 -89
  388. package/skills/developing-agentforce/assets/patterns/lifecycle-events.agent +0 -127
  389. package/skills/developing-agentforce/assets/patterns/llm-controlled-actions.agent +0 -184
  390. package/skills/developing-agentforce/assets/patterns/multi-step-workflow.agent +0 -282
  391. package/skills/developing-agentforce/assets/patterns/open-gate-routing.agent +0 -287
  392. package/skills/developing-agentforce/assets/patterns/procedural-instructions.agent +0 -273
  393. package/skills/developing-agentforce/assets/patterns/prompt-template-action.agent +0 -188
  394. package/skills/developing-agentforce/assets/patterns/system-instruction-overrides.agent +0 -293
  395. package/skills/developing-agentforce/assets/prompt-rag-search.agent +0 -131
  396. package/skills/developing-agentforce/assets/template-multi-subagent.agent +0 -160
  397. package/skills/developing-agentforce/assets/template-single-subagent.agent +0 -81
  398. package/skills/developing-agentforce/assets/verification-gate.agent +0 -208
  399. package/skills/developing-agentforce/references/action-prompt-templates.md +0 -164
  400. package/skills/developing-agentforce/references/actions-reference.md +0 -612
  401. package/skills/developing-agentforce/references/agent-access-guide.md +0 -72
  402. package/skills/developing-agentforce/references/agent-design-and-spec-creation.md +0 -1010
  403. package/skills/developing-agentforce/references/agent-metadata-and-lifecycle.md +0 -575
  404. package/skills/developing-agentforce/references/agent-script-core-language.md +0 -1255
  405. package/skills/developing-agentforce/references/agent-subagent-map-diagrams.md +0 -323
  406. package/skills/developing-agentforce/references/agent-user-setup.md +0 -529
  407. package/skills/developing-agentforce/references/agent-validation-and-debugging.md +0 -805
  408. package/skills/developing-agentforce/references/architecture-patterns.md +0 -158
  409. package/skills/developing-agentforce/references/complex-data-types.md +0 -57
  410. package/skills/developing-agentforce/references/deploy-reference.md +0 -134
  411. package/skills/developing-agentforce/references/discover-reference.md +0 -102
  412. package/skills/developing-agentforce/references/examples.md +0 -350
  413. package/skills/developing-agentforce/references/feature-validity.md +0 -43
  414. package/skills/developing-agentforce/references/instruction-resolution.md +0 -545
  415. package/skills/developing-agentforce/references/known-issues.md +0 -353
  416. package/skills/developing-agentforce/references/minimal-examples.md +0 -67
  417. package/skills/developing-agentforce/references/production-gotchas.md +0 -300
  418. package/skills/developing-agentforce/references/safety-review-reference.md +0 -145
  419. package/skills/developing-agentforce/references/salesforce-cli-for-agents.md +0 -395
  420. package/skills/developing-agentforce/references/scaffold-reference.md +0 -153
  421. package/skills/developing-agentforce/references/scoring-rubric.md +0 -24
  422. package/skills/developing-agentforce/references/version-history.md +0 -23
  423. package/skills/dx-app-analytics-use/SKILL.md +0 -135
  424. package/skills/fetching-salesforce-docs/README.md +0 -66
  425. package/skills/fetching-salesforce-docs/SKILL.md +0 -208
  426. package/skills/fetching-salesforce-docs/requirements.txt +0 -2
  427. package/skills/fetching-salesforce-docs/scripts/extract_help_salesforce.py +0 -497
  428. package/skills/fetching-salesforce-docs/scripts/extract_salesforce_doc.py +0 -357
  429. package/skills/fetching-salesforce-docs/scripts/runtime_bootstrap.py +0 -58
  430. package/skills/generating-apex/CREDITS.md +0 -5
  431. package/skills/generating-apex/SKILL.md +0 -409
  432. package/skills/generating-apex/assets/abstract.cls +0 -131
  433. package/skills/generating-apex/assets/batch.cls +0 -124
  434. package/skills/generating-apex/assets/domain.cls +0 -101
  435. package/skills/generating-apex/assets/dto.cls +0 -107
  436. package/skills/generating-apex/assets/exception.cls +0 -50
  437. package/skills/generating-apex/assets/interface.cls +0 -24
  438. package/skills/generating-apex/assets/invocable.cls +0 -114
  439. package/skills/generating-apex/assets/queueable.cls +0 -91
  440. package/skills/generating-apex/assets/rest-resource.cls +0 -300
  441. package/skills/generating-apex/assets/schedulable.cls +0 -74
  442. package/skills/generating-apex/assets/selector.cls +0 -91
  443. package/skills/generating-apex/assets/service.cls +0 -68
  444. package/skills/generating-apex/assets/trigger.cls +0 -45
  445. package/skills/generating-apex/assets/utility.cls +0 -96
  446. package/skills/generating-apex/references/AccountDeduplicationBatch.cls +0 -147
  447. package/skills/generating-apex/references/AccountSelector.cls +0 -192
  448. package/skills/generating-apex/references/AccountService.cls +0 -200
  449. package/skills/generating-apex-test/CREDITS.md +0 -5
  450. package/skills/generating-apex-test/SKILL.md +0 -201
  451. package/skills/generating-apex-test/assets/test-class-template.cls +0 -93
  452. package/skills/generating-apex-test/assets/test-data-factory-template.cls +0 -111
  453. package/skills/generating-apex-test/references/assertion-patterns.md +0 -108
  454. package/skills/generating-apex-test/references/async-testing.md +0 -193
  455. package/skills/generating-apex-test/references/mocking-patterns.md +0 -220
  456. package/skills/generating-apex-test/references/test-data-factory.md +0 -75
  457. package/skills/generating-custom-application/SKILL.md +0 -211
  458. package/skills/generating-custom-field/SKILL.md +0 -503
  459. package/skills/generating-custom-lightning-type/SKILL.md +0 -180
  460. package/skills/generating-custom-lightning-type/assets/primitive-types-and-constraints.md +0 -41
  461. package/skills/generating-custom-lightning-type/references/widget-rendition.md +0 -124
  462. package/skills/generating-custom-object/SKILL.md +0 -240
  463. package/skills/generating-custom-tab/SKILL.md +0 -156
  464. package/skills/generating-flexipage/SKILL.md +0 -522
  465. package/skills/generating-flow/SKILL.md +0 -372
  466. package/skills/generating-lightning-app/SKILL.md +0 -423
  467. package/skills/generating-list-view/SKILL.md +0 -218
  468. package/skills/generating-lwc-components/CREDITS.md +0 -5
  469. package/skills/generating-lwc-components/README.md +0 -126
  470. package/skills/generating-lwc-components/SKILL.md +0 -190
  471. package/skills/generating-lwc-components/assets/apex-controller/LwcController.cls +0 -327
  472. package/skills/generating-lwc-components/assets/basic-component/basicComponent.css +0 -72
  473. package/skills/generating-lwc-components/assets/basic-component/basicComponent.html +0 -111
  474. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js +0 -163
  475. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js-meta.xml +0 -137
  476. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.html +0 -111
  477. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.js +0 -367
  478. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.css +0 -63
  479. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.html +0 -154
  480. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js +0 -348
  481. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js-meta.xml +0 -87
  482. package/skills/generating-lwc-components/assets/form-component/formComponent.html +0 -165
  483. package/skills/generating-lwc-components/assets/form-component/formComponent.js +0 -275
  484. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.html +0 -100
  485. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.js +0 -336
  486. package/skills/generating-lwc-components/assets/jest-test/componentName.test.js.example +0 -371
  487. package/skills/generating-lwc-components/assets/message-channel/RecordSelected.messageChannel-meta.xml +0 -71
  488. package/skills/generating-lwc-components/assets/message-channel/lmsPublisher.js +0 -103
  489. package/skills/generating-lwc-components/assets/message-channel/lmsSubscriber.js +0 -181
  490. package/skills/generating-lwc-components/assets/modal-component/modalComponent.html +0 -85
  491. package/skills/generating-lwc-components/assets/modal-component/modalComponent.js +0 -199
  492. package/skills/generating-lwc-components/assets/record-picker/recordPicker.html +0 -55
  493. package/skills/generating-lwc-components/assets/record-picker/recordPicker.js +0 -199
  494. package/skills/generating-lwc-components/assets/state-store/store.js +0 -282
  495. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.css +0 -65
  496. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.html +0 -95
  497. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.js-meta.xml +0 -75
  498. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.test.ts.example +0 -301
  499. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.ts +0 -295
  500. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.html +0 -71
  501. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.js +0 -316
  502. package/skills/generating-lwc-components/hooks/scripts/lwc-lsp-validate.py +0 -295
  503. package/skills/generating-lwc-components/hooks/scripts/post-tool-validate.py +0 -347
  504. package/skills/generating-lwc-components/hooks/scripts/slds_data/deprecated_patterns.json +0 -74
  505. package/skills/generating-lwc-components/hooks/scripts/slds_data/styling_hooks.json +0 -111
  506. package/skills/generating-lwc-components/hooks/scripts/slds_data/valid_slds_classes.json +0 -127
  507. package/skills/generating-lwc-components/hooks/scripts/slds_linter_wrapper.py +0 -294
  508. package/skills/generating-lwc-components/hooks/scripts/slds_rules/__init__.py +0 -22
  509. package/skills/generating-lwc-components/hooks/scripts/template_validator.py +0 -332
  510. package/skills/generating-lwc-components/hooks/scripts/validate_slds.py +0 -595
  511. package/skills/generating-lwc-components/references/accessibility-guide.md +0 -843
  512. package/skills/generating-lwc-components/references/advanced-features.md +0 -108
  513. package/skills/generating-lwc-components/references/async-notification-patterns.md +0 -661
  514. package/skills/generating-lwc-components/references/cli-commands.md +0 -545
  515. package/skills/generating-lwc-components/references/component-patterns.md +0 -1476
  516. package/skills/generating-lwc-components/references/flow-integration-guide.md +0 -675
  517. package/skills/generating-lwc-components/references/jest-testing.md +0 -1011
  518. package/skills/generating-lwc-components/references/lms-guide.md +0 -860
  519. package/skills/generating-lwc-components/references/lwc-best-practices.md +0 -1310
  520. package/skills/generating-lwc-components/references/performance-guide.md +0 -861
  521. package/skills/generating-lwc-components/references/scoring-and-testing.md +0 -116
  522. package/skills/generating-lwc-components/references/slds-blueprints.json +0 -14389
  523. package/skills/generating-lwc-components/references/slds-design-guide.md +0 -166
  524. package/skills/generating-lwc-components/references/state-management.md +0 -642
  525. package/skills/generating-lwc-components/references/template-anti-patterns.md +0 -948
  526. package/skills/generating-lwc-components/references/triangle-pattern.md +0 -365
  527. package/skills/generating-lwc-components/scripts/local-dev-preview.sh +0 -34
  528. package/skills/generating-mermaid-diagrams/CREDITS.md +0 -46
  529. package/skills/generating-mermaid-diagrams/README.md +0 -114
  530. package/skills/generating-mermaid-diagrams/SKILL.md +0 -217
  531. package/skills/generating-mermaid-diagrams/assets/agentforce/agent-flow.md +0 -313
  532. package/skills/generating-mermaid-diagrams/assets/architecture/system-landscape.md +0 -351
  533. package/skills/generating-mermaid-diagrams/assets/datamodel/b2b-commerce-erd.md +0 -317
  534. package/skills/generating-mermaid-diagrams/assets/datamodel/campaigns-erd.md +0 -195
  535. package/skills/generating-mermaid-diagrams/assets/datamodel/consent-erd.md +0 -262
  536. package/skills/generating-mermaid-diagrams/assets/datamodel/files-erd.md +0 -266
  537. package/skills/generating-mermaid-diagrams/assets/datamodel/forecasting-erd.md +0 -261
  538. package/skills/generating-mermaid-diagrams/assets/datamodel/fsl-erd.md +0 -332
  539. package/skills/generating-mermaid-diagrams/assets/datamodel/party-model-erd.md +0 -237
  540. package/skills/generating-mermaid-diagrams/assets/datamodel/quote-order-erd.md +0 -277
  541. package/skills/generating-mermaid-diagrams/assets/datamodel/revenue-cloud-erd.md +0 -343
  542. package/skills/generating-mermaid-diagrams/assets/datamodel/sales-cloud-erd.md +0 -192
  543. package/skills/generating-mermaid-diagrams/assets/datamodel/salesforce-erd.md +0 -209
  544. package/skills/generating-mermaid-diagrams/assets/datamodel/scheduler-erd.md +0 -276
  545. package/skills/generating-mermaid-diagrams/assets/datamodel/service-cloud-erd.md +0 -217
  546. package/skills/generating-mermaid-diagrams/assets/datamodel/territory-management-erd.md +0 -241
  547. package/skills/generating-mermaid-diagrams/assets/integration/api-sequence.md +0 -387
  548. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code-pkce.md +0 -197
  549. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code.md +0 -152
  550. package/skills/generating-mermaid-diagrams/assets/oauth/client-credentials.md +0 -233
  551. package/skills/generating-mermaid-diagrams/assets/oauth/device-authorization.md +0 -295
  552. package/skills/generating-mermaid-diagrams/assets/oauth/jwt-bearer.md +0 -256
  553. package/skills/generating-mermaid-diagrams/assets/oauth/refresh-token.md +0 -281
  554. package/skills/generating-mermaid-diagrams/assets/oauth/user-agent-social-sign-on.md +0 -281
  555. package/skills/generating-mermaid-diagrams/assets/role-hierarchy/user-hierarchy.md +0 -322
  556. package/skills/generating-mermaid-diagrams/references/color-palette.md +0 -464
  557. package/skills/generating-mermaid-diagrams/references/diagram-conventions.md +0 -313
  558. package/skills/generating-mermaid-diagrams/references/erd-conventions.md +0 -320
  559. package/skills/generating-mermaid-diagrams/references/mermaid-reference.md +0 -434
  560. package/skills/generating-mermaid-diagrams/references/mermaid-styling.md +0 -81
  561. package/skills/generating-mermaid-diagrams/references/preview-guide.md +0 -46
  562. package/skills/generating-mermaid-diagrams/references/usage-examples.md +0 -340
  563. package/skills/generating-mermaid-diagrams/scripts/README.md +0 -160
  564. package/skills/generating-mermaid-diagrams/scripts/mermaid_preview.py +0 -654
  565. package/skills/generating-mermaid-diagrams/scripts/query-org-metadata.py +0 -293
  566. package/skills/generating-permission-set/SKILL.md +0 -189
  567. package/skills/generating-ui-bundle-custom-app/SKILL.md +0 -93
  568. package/skills/generating-ui-bundle-custom-app/docs/configure-metadata-custom-application.md +0 -70
  569. package/skills/generating-ui-bundle-features/SKILL.md +0 -47
  570. package/skills/generating-ui-bundle-metadata/SKILL.md +0 -153
  571. package/skills/generating-ui-bundle-metadata/implementation/csp-metadata-format.md +0 -281
  572. package/skills/generating-ui-bundle-site/SKILL.md +0 -92
  573. package/skills/generating-ui-bundle-site/docs/configure-metadata-custom-site.md +0 -41
  574. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience-bundle.md +0 -17
  575. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience-config.md +0 -21
  576. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience.md +0 -40
  577. package/skills/generating-ui-bundle-site/docs/configure-metadata-network.md +0 -72
  578. package/skills/generating-ui-bundle-site/docs/update-site-urls.md +0 -100
  579. package/skills/generating-validation-rule/SKILL.md +0 -74
  580. package/skills/generating-visual-diagrams/CREDITS.md +0 -80
  581. package/skills/generating-visual-diagrams/README.md +0 -83
  582. package/skills/generating-visual-diagrams/SKILL.md +0 -207
  583. package/skills/generating-visual-diagrams/assets/architecture/integration-flow.md +0 -55
  584. package/skills/generating-visual-diagrams/assets/erd/core-objects.md +0 -131
  585. package/skills/generating-visual-diagrams/assets/erd/custom-objects.md +0 -60
  586. package/skills/generating-visual-diagrams/assets/lwc/dashboard-card.md +0 -45
  587. package/skills/generating-visual-diagrams/assets/lwc/data-table.md +0 -57
  588. package/skills/generating-visual-diagrams/assets/lwc/record-form.md +0 -60
  589. package/skills/generating-visual-diagrams/assets/review/apex-review.md +0 -57
  590. package/skills/generating-visual-diagrams/assets/review/lwc-review.md +0 -48
  591. package/skills/generating-visual-diagrams/references/architect-aesthetic-guide.md +0 -257
  592. package/skills/generating-visual-diagrams/references/examples-index.md +0 -35
  593. package/skills/generating-visual-diagrams/references/gemini-cli-setup.md +0 -65
  594. package/skills/generating-visual-diagrams/references/interview-questions.md +0 -529
  595. package/skills/generating-visual-diagrams/references/iteration-workflow.md +0 -173
  596. package/skills/generating-visual-diagrams/scripts/check-prerequisites.sh +0 -101
  597. package/skills/generating-visual-diagrams/scripts/generate_image.py +0 -243
  598. package/skills/getting-metadata-api-context/README.md +0 -79
  599. package/skills/getting-metadata-api-context/SKILL.md +0 -466
  600. package/skills/getting-metadata-api-context/data/metadata_api/AIApplication.json +0 -37
  601. package/skills/getting-metadata-api-context/data/metadata_api/AIApplicationConfig.json +0 -53
  602. package/skills/getting-metadata-api-context/data/metadata_api/AIReplyRecommendationsSettings.json +0 -40
  603. package/skills/getting-metadata-api-context/data/metadata_api/AIScoringModelDefinition.json +0 -87
  604. package/skills/getting-metadata-api-context/data/metadata_api/AIUsecaseDefinition.json +0 -215
  605. package/skills/getting-metadata-api-context/data/metadata_api/AccountInsightsSettings.json +0 -30
  606. package/skills/getting-metadata-api-context/data/metadata_api/AccountIntelligenceSettings.json +0 -40
  607. package/skills/getting-metadata-api-context/data/metadata_api/AccountPlanObjMeasCalcDef.json +0 -86
  608. package/skills/getting-metadata-api-context/data/metadata_api/AccountPlanSettings.json +0 -32
  609. package/skills/getting-metadata-api-context/data/metadata_api/AccountRelationshipShareRule.json +0 -56
  610. package/skills/getting-metadata-api-context/data/metadata_api/AccountSettings.json +0 -64
  611. package/skills/getting-metadata-api-context/data/metadata_api/AccountingFieldMapping.json +0 -70
  612. package/skills/getting-metadata-api-context/data/metadata_api/AccountingModelConfig.json +0 -94
  613. package/skills/getting-metadata-api-context/data/metadata_api/AccountingSettings.json +0 -53
  614. package/skills/getting-metadata-api-context/data/metadata_api/ActionLinkGroupTemplate.json +0 -118
  615. package/skills/getting-metadata-api-context/data/metadata_api/ActionOverride.json +0 -70
  616. package/skills/getting-metadata-api-context/data/metadata_api/ActionPlanTemplate.json +0 -166
  617. package/skills/getting-metadata-api-context/data/metadata_api/ActionableListDefinition.json +0 -114
  618. package/skills/getting-metadata-api-context/data/metadata_api/ActionsSettings.json +0 -44
  619. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatform.json +0 -95
  620. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatformActvAttr.json +0 -8
  621. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatformField.json +0 -55
  622. package/skills/getting-metadata-api-context/data/metadata_api/ActivitiesSettings.json +0 -136
  623. package/skills/getting-metadata-api-context/data/metadata_api/ActvPfrmDataConnectorS3.json +0 -41
  624. package/skills/getting-metadata-api-context/data/metadata_api/ActvPlatformAdncIdentifier.json +0 -46
  625. package/skills/getting-metadata-api-context/data/metadata_api/ActvPlatformFieldValue.json +0 -50
  626. package/skills/getting-metadata-api-context/data/metadata_api/AddressSettings.json +0 -90
  627. package/skills/getting-metadata-api-context/data/metadata_api/AdvAccountForecastSet.json +0 -261
  628. package/skills/getting-metadata-api-context/data/metadata_api/AffinityScoreDefinition.json +0 -74
  629. package/skills/getting-metadata-api-context/data/metadata_api/AgentPlatformSettings.json +0 -32
  630. package/skills/getting-metadata-api-context/data/metadata_api/AgentforceForDevelopersSettings.json +0 -32
  631. package/skills/getting-metadata-api-context/data/metadata_api/AiAuthoringBundle.json +0 -44
  632. package/skills/getting-metadata-api-context/data/metadata_api/AiEvaluationDefinition.json +0 -153
  633. package/skills/getting-metadata-api-context/data/metadata_api/AiPluginUtteranceDef.json +0 -40
  634. package/skills/getting-metadata-api-context/data/metadata_api/AllOrNoneHeader.json +0 -17
  635. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticSnapshot.json +0 -80
  636. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsDashboard.json +0 -369
  637. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsSettings.json +0 -488
  638. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsVisualization.json +0 -180
  639. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsWorkspace.json +0 -71
  640. package/skills/getting-metadata-api-context/data/metadata_api/AnimationRule.json +0 -71
  641. package/skills/getting-metadata-api-context/data/metadata_api/ApexClass.json +0 -70
  642. package/skills/getting-metadata-api-context/data/metadata_api/ApexComponent.json +0 -44
  643. package/skills/getting-metadata-api-context/data/metadata_api/ApexEmailNotifications.json +0 -49
  644. package/skills/getting-metadata-api-context/data/metadata_api/ApexPage.json +0 -64
  645. package/skills/getting-metadata-api-context/data/metadata_api/ApexSettings.json +0 -96
  646. package/skills/getting-metadata-api-context/data/metadata_api/ApexTestSuite.json +0 -32
  647. package/skills/getting-metadata-api-context/data/metadata_api/ApexTrigger.json +0 -52
  648. package/skills/getting-metadata-api-context/data/metadata_api/AppAnalyticsSettings.json +0 -36
  649. package/skills/getting-metadata-api-context/data/metadata_api/AppExperienceSettings.json +0 -32
  650. package/skills/getting-metadata-api-context/data/metadata_api/AppFrameworkTemplateBundle.json +0 -52
  651. package/skills/getting-metadata-api-context/data/metadata_api/AppMenu.json +0 -10
  652. package/skills/getting-metadata-api-context/data/metadata_api/AppointmentAssignmentPolicy.json +0 -48
  653. package/skills/getting-metadata-api-context/data/metadata_api/AppointmentSchedulingPolicy.json +0 -102
  654. package/skills/getting-metadata-api-context/data/metadata_api/ApprovalProcess.json +0 -234
  655. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType.json +0 -81
  656. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType_CustomField.json +0 -88
  657. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType_Layout.json +0 -63
  658. package/skills/getting-metadata-api-context/data/metadata_api/AssessmentQuestion.json +0 -117
  659. package/skills/getting-metadata-api-context/data/metadata_api/AssessmentQuestionSet.json +0 -41
  660. package/skills/getting-metadata-api-context/data/metadata_api/AssignmentRules.json +0 -87
  661. package/skills/getting-metadata-api-context/data/metadata_api/AssociationEngineSettings.json +0 -32
  662. package/skills/getting-metadata-api-context/data/metadata_api/AsyncResult.json +0 -89
  663. package/skills/getting-metadata-api-context/data/metadata_api/Audience.json +0 -172
  664. package/skills/getting-metadata-api-context/data/metadata_api/AuraDefinitionBundle.json +0 -94
  665. package/skills/getting-metadata-api-context/data/metadata_api/AuthProvider.json +0 -169
  666. package/skills/getting-metadata-api-context/data/metadata_api/AutoResponseRules.json +0 -79
  667. package/skills/getting-metadata-api-context/data/metadata_api/AutomatedContactsSettings.json +0 -44
  668. package/skills/getting-metadata-api-context/data/metadata_api/BaseSharingRule.json +0 -24
  669. package/skills/getting-metadata-api-context/data/metadata_api/BatchCalcJobDefinition.json +0 -849
  670. package/skills/getting-metadata-api-context/data/metadata_api/BatchProcessJobDefinition.json +0 -175
  671. package/skills/getting-metadata-api-context/data/metadata_api/BillingSettings.json +0 -152
  672. package/skills/getting-metadata-api-context/data/metadata_api/BlacklistedConsumer.json +0 -47
  673. package/skills/getting-metadata-api-context/data/metadata_api/Bot.json +0 -197
  674. package/skills/getting-metadata-api-context/data/metadata_api/BotBlock.json +0 -86
  675. package/skills/getting-metadata-api-context/data/metadata_api/BotSettings.json +0 -32
  676. package/skills/getting-metadata-api-context/data/metadata_api/BotTemplate.json +0 -96
  677. package/skills/getting-metadata-api-context/data/metadata_api/BotVersion.json +0 -667
  678. package/skills/getting-metadata-api-context/data/metadata_api/BranchManagementSettings.json +0 -32
  679. package/skills/getting-metadata-api-context/data/metadata_api/BrandingSet.json +0 -146
  680. package/skills/getting-metadata-api-context/data/metadata_api/BriefcaseDefinition.json +0 -127
  681. package/skills/getting-metadata-api-context/data/metadata_api/BusinessHoursSettings.json +0 -175
  682. package/skills/getting-metadata-api-context/data/metadata_api/BusinessProcess.json +0 -47
  683. package/skills/getting-metadata-api-context/data/metadata_api/BusinessProcessGroup.json +0 -91
  684. package/skills/getting-metadata-api-context/data/metadata_api/CMSConnectSource.json +0 -197
  685. package/skills/getting-metadata-api-context/data/metadata_api/CallCenter.json +0 -124
  686. package/skills/getting-metadata-api-context/data/metadata_api/CallCenterRoutingMap.json +0 -58
  687. package/skills/getting-metadata-api-context/data/metadata_api/CallCoachingMediaProvider.json +0 -40
  688. package/skills/getting-metadata-api-context/data/metadata_api/CallOptions.json +0 -17
  689. package/skills/getting-metadata-api-context/data/metadata_api/CampaignInfluenceModel.json +0 -59
  690. package/skills/getting-metadata-api-context/data/metadata_api/CampaignSettings.json +0 -71
  691. package/skills/getting-metadata-api-context/data/metadata_api/CancelDeployResult.json +0 -10
  692. package/skills/getting-metadata-api-context/data/metadata_api/CareBenefitVerifySettings.json +0 -70
  693. package/skills/getting-metadata-api-context/data/metadata_api/CareLimitType.json +0 -46
  694. package/skills/getting-metadata-api-context/data/metadata_api/CareProviderSearchConfig.json +0 -54
  695. package/skills/getting-metadata-api-context/data/metadata_api/CareRequestConfiguration.json +0 -57
  696. package/skills/getting-metadata-api-context/data/metadata_api/CareSystemFieldMapping.json +0 -58
  697. package/skills/getting-metadata-api-context/data/metadata_api/CaseSettings.json +0 -423
  698. package/skills/getting-metadata-api-context/data/metadata_api/CaseSubjectParticle.json +0 -35
  699. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApi.json +0 -97
  700. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApiArtifactVersionInfo.json +0 -46
  701. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApiVersion.json +0 -51
  702. package/skills/getting-metadata-api-context/data/metadata_api/Certificate.json +0 -54
  703. package/skills/getting-metadata-api-context/data/metadata_api/ChannelLayout.json +0 -63
  704. package/skills/getting-metadata-api-context/data/metadata_api/ChatterAnswersSettings.json +0 -76
  705. package/skills/getting-metadata-api-context/data/metadata_api/ChatterEmailsMDSettings.json +0 -68
  706. package/skills/getting-metadata-api-context/data/metadata_api/ChatterExtension.json +0 -64
  707. package/skills/getting-metadata-api-context/data/metadata_api/ChatterSettings.json +0 -92
  708. package/skills/getting-metadata-api-context/data/metadata_api/ChoiceList.json +0 -66
  709. package/skills/getting-metadata-api-context/data/metadata_api/ClaimFinancialSettings.json +0 -51
  710. package/skills/getting-metadata-api-context/data/metadata_api/ClauseCatgConfiguration.json +0 -45
  711. package/skills/getting-metadata-api-context/data/metadata_api/CleanDataService.json +0 -166
  712. package/skills/getting-metadata-api-context/data/metadata_api/CodeBuilderSettings.json +0 -32
  713. package/skills/getting-metadata-api-context/data/metadata_api/CollectionsDashboardSettings.json +0 -32
  714. package/skills/getting-metadata-api-context/data/metadata_api/CommerceSettings.json +0 -80
  715. package/skills/getting-metadata-api-context/data/metadata_api/CommunitiesSettings.json +0 -116
  716. package/skills/getting-metadata-api-context/data/metadata_api/Community.json +0 -121
  717. package/skills/getting-metadata-api-context/data/metadata_api/CommunityTemplateDefinition.json +0 -116
  718. package/skills/getting-metadata-api-context/data/metadata_api/CommunityThemeDefinition.json +0 -146
  719. package/skills/getting-metadata-api-context/data/metadata_api/CompactLayout.json +0 -32
  720. package/skills/getting-metadata-api-context/data/metadata_api/CompanySettings.json +0 -49
  721. package/skills/getting-metadata-api-context/data/metadata_api/ConnectedApp.json +0 -384
  722. package/skills/getting-metadata-api-context/data/metadata_api/ConnectedAppSettings.json +0 -40
  723. package/skills/getting-metadata-api-context/data/metadata_api/ContentAsset.json +0 -121
  724. package/skills/getting-metadata-api-context/data/metadata_api/ContentSettings.json +0 -116
  725. package/skills/getting-metadata-api-context/data/metadata_api/ContentTypeBundle.json +0 -64
  726. package/skills/getting-metadata-api-context/data/metadata_api/ContextDefinition.json +0 -340
  727. package/skills/getting-metadata-api-context/data/metadata_api/ContractSettings.json +0 -36
  728. package/skills/getting-metadata-api-context/data/metadata_api/ConvIntelligenceSignalRule.json +0 -106
  729. package/skills/getting-metadata-api-context/data/metadata_api/ConversationChannelDefinition.json +0 -140
  730. package/skills/getting-metadata-api-context/data/metadata_api/ConversationMessageDefinition.json +0 -380
  731. package/skills/getting-metadata-api-context/data/metadata_api/ConversationMessageDefinitionTranslation.json +0 -49
  732. package/skills/getting-metadata-api-context/data/metadata_api/ConversationVendorInfo.json +0 -148
  733. package/skills/getting-metadata-api-context/data/metadata_api/ConversationalIntelligenceSettings.json +0 -76
  734. package/skills/getting-metadata-api-context/data/metadata_api/CorsWhitelistOrigin.json +0 -32
  735. package/skills/getting-metadata-api-context/data/metadata_api/CriteriaBasedSharingRule.json +0 -206
  736. package/skills/getting-metadata-api-context/data/metadata_api/CspTrustedSite.json +0 -82
  737. package/skills/getting-metadata-api-context/data/metadata_api/CurrencySettings.json +0 -48
  738. package/skills/getting-metadata-api-context/data/metadata_api/CustomAddressFieldSettings.json +0 -32
  739. package/skills/getting-metadata-api-context/data/metadata_api/CustomApplication.json +0 -453
  740. package/skills/getting-metadata-api-context/data/metadata_api/CustomApplicationComponent.json +0 -72
  741. package/skills/getting-metadata-api-context/data/metadata_api/CustomFeedFilter.json +0 -63
  742. package/skills/getting-metadata-api-context/data/metadata_api/CustomField.json +0 -392
  743. package/skills/getting-metadata-api-context/data/metadata_api/CustomFieldDisplay.json +0 -45
  744. package/skills/getting-metadata-api-context/data/metadata_api/CustomHelpMenuSection.json +0 -57
  745. package/skills/getting-metadata-api-context/data/metadata_api/CustomIndex.json +0 -36
  746. package/skills/getting-metadata-api-context/data/metadata_api/CustomLabels.json +0 -69
  747. package/skills/getting-metadata-api-context/data/metadata_api/CustomMetadata.json +0 -90
  748. package/skills/getting-metadata-api-context/data/metadata_api/CustomNotificationType.json +0 -94
  749. package/skills/getting-metadata-api-context/data/metadata_api/CustomObject.json +0 -313
  750. package/skills/getting-metadata-api-context/data/metadata_api/CustomObjectTranslation.json +0 -319
  751. package/skills/getting-metadata-api-context/data/metadata_api/CustomPageWebLink.json +0 -121
  752. package/skills/getting-metadata-api-context/data/metadata_api/CustomPermission.json +0 -65
  753. package/skills/getting-metadata-api-context/data/metadata_api/CustomSite.json +0 -288
  754. package/skills/getting-metadata-api-context/data/metadata_api/CustomTab.json +0 -97
  755. package/skills/getting-metadata-api-context/data/metadata_api/CustomValue.json +0 -85
  756. package/skills/getting-metadata-api-context/data/metadata_api/CustomerDataPlatformSettings.json +0 -32
  757. package/skills/getting-metadata-api-context/data/metadata_api/Dashboard.json +0 -584
  758. package/skills/getting-metadata-api-context/data/metadata_api/DataCategoryGroup.json +0 -81
  759. package/skills/getting-metadata-api-context/data/metadata_api/DataConnector.json +0 -230
  760. package/skills/getting-metadata-api-context/data/metadata_api/DataConnectorIngestApi.json +0 -41
  761. package/skills/getting-metadata-api-context/data/metadata_api/DataConnectorS3.json +0 -44
  762. package/skills/getting-metadata-api-context/data/metadata_api/DataDotComSettings.json +0 -56
  763. package/skills/getting-metadata-api-context/data/metadata_api/DataImportManagementSettings.json +0 -32
  764. package/skills/getting-metadata-api-context/data/metadata_api/DataKitObjectDependency.json +0 -49
  765. package/skills/getting-metadata-api-context/data/metadata_api/DataKitObjectTemplate.json +0 -59
  766. package/skills/getting-metadata-api-context/data/metadata_api/DataObjectBuildOrgTemplate.json +0 -61
  767. package/skills/getting-metadata-api-context/data/metadata_api/DataObjectSearchIndexConf.json +0 -62
  768. package/skills/getting-metadata-api-context/data/metadata_api/DataPackageKitDefinition.json +0 -74
  769. package/skills/getting-metadata-api-context/data/metadata_api/DataPackageKitObject.json +0 -47
  770. package/skills/getting-metadata-api-context/data/metadata_api/DataSource.json +0 -29
  771. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceBundleDefinition.json +0 -57
  772. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceField.json +0 -115
  773. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceObject.json +0 -93
  774. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceTenant.json +0 -8
  775. package/skills/getting-metadata-api-context/data/metadata_api/DataSrcDataModelFieldMap.json +0 -69
  776. package/skills/getting-metadata-api-context/data/metadata_api/DataStreamDefinition.json +0 -105
  777. package/skills/getting-metadata-api-context/data/metadata_api/DataStreamTemplate.json +0 -99
  778. package/skills/getting-metadata-api-context/data/metadata_api/DataWeaveResource.json +0 -46
  779. package/skills/getting-metadata-api-context/data/metadata_api/DebuggingHeader.json +0 -20
  780. package/skills/getting-metadata-api-context/data/metadata_api/DecisionMatrixDefinition.json +0 -140
  781. package/skills/getting-metadata-api-context/data/metadata_api/DecisionTable.json +0 -211
  782. package/skills/getting-metadata-api-context/data/metadata_api/DecisionTableDatasetLink.json +0 -72
  783. package/skills/getting-metadata-api-context/data/metadata_api/DelegateGroup.json +0 -62
  784. package/skills/getting-metadata-api-context/data/metadata_api/DeleteResult.json +0 -22
  785. package/skills/getting-metadata-api-context/data/metadata_api/DeployResult.json +0 -253
  786. package/skills/getting-metadata-api-context/data/metadata_api/DeploymentSettings.json +0 -32
  787. package/skills/getting-metadata-api-context/data/metadata_api/DescribeMetadataResult.json +0 -31
  788. package/skills/getting-metadata-api-context/data/metadata_api/DescribeValueTypeResult.json +0 -56
  789. package/skills/getting-metadata-api-context/data/metadata_api/DevHubSettings.json +0 -60
  790. package/skills/getting-metadata-api-context/data/metadata_api/DgtAssetMgmtProvider.json +0 -43
  791. package/skills/getting-metadata-api-context/data/metadata_api/DgtAssetMgmtPrvdLghtCpnt.json +0 -48
  792. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle.json +0 -102
  793. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle_Marketing_Workspace_Bundle_and_Folders.json +0 -8
  794. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle_Site_Workspace_Bundle_and_Folders.json +0 -541
  795. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceConfig.json +0 -51
  796. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureDefinition.json +0 -45
  797. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureDefinitionVersion.json +0 -78
  798. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureType.json +0 -53
  799. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryAIModel.json +0 -263
  800. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryGoal.json +0 -361
  801. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryStory.json +0 -98
  802. package/skills/getting-metadata-api-context/data/metadata_api/Document.json +0 -54
  803. package/skills/getting-metadata-api-context/data/metadata_api/DocumentCategory.json +0 -42
  804. package/skills/getting-metadata-api-context/data/metadata_api/DocumentCategoryDocumentType.json +0 -48
  805. package/skills/getting-metadata-api-context/data/metadata_api/DocumentChecklistSettings.json +0 -36
  806. package/skills/getting-metadata-api-context/data/metadata_api/DocumentGenerationSetting.json +0 -60
  807. package/skills/getting-metadata-api-context/data/metadata_api/DocumentType.json +0 -43
  808. package/skills/getting-metadata-api-context/data/metadata_api/DuplicateRule.json +0 -160
  809. package/skills/getting-metadata-api-context/data/metadata_api/DynamicFormsSettings.json +0 -32
  810. package/skills/getting-metadata-api-context/data/metadata_api/EACSettings.json +0 -112
  811. package/skills/getting-metadata-api-context/data/metadata_api/EclairGeoData.json +0 -73
  812. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinAISettings.json +0 -45
  813. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinAgentSettings.json +0 -40
  814. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinGptSettings.json +0 -64
  815. package/skills/getting-metadata-api-context/data/metadata_api/EmailAdministrationSettings.json +0 -104
  816. package/skills/getting-metadata-api-context/data/metadata_api/EmailAuthorizationSettings.json +0 -32
  817. package/skills/getting-metadata-api-context/data/metadata_api/EmailIntegrationSettings.json +0 -92
  818. package/skills/getting-metadata-api-context/data/metadata_api/EmailServicesFunction.json +0 -116
  819. package/skills/getting-metadata-api-context/data/metadata_api/EmailTemplate.json +0 -116
  820. package/skills/getting-metadata-api-context/data/metadata_api/EmailTemplateSettings.json +0 -32
  821. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceBranding.json +0 -78
  822. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceConfig.json +0 -318
  823. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceFieldService.json +0 -73
  824. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceFlowConfig.json +0 -32
  825. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceLiveAgent.json +0 -141
  826. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceMenuSettings.json +0 -165
  827. package/skills/getting-metadata-api-context/data/metadata_api/EmployeeUserSettings.json +0 -54
  828. package/skills/getting-metadata-api-context/data/metadata_api/EnablementMeasureDefinition.json +0 -139
  829. package/skills/getting-metadata-api-context/data/metadata_api/EnablementProgramDefinition.json +0 -241
  830. package/skills/getting-metadata-api-context/data/metadata_api/EnblProgramTaskSubCategory.json +0 -47
  831. package/skills/getting-metadata-api-context/data/metadata_api/EncryptionKeySettings.json +0 -51
  832. package/skills/getting-metadata-api-context/data/metadata_api/EnhancedNotesSettings.json +0 -36
  833. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementProcess.json +0 -147
  834. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementSettings.json +0 -80
  835. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementTemplate.json +0 -52
  836. package/skills/getting-metadata-api-context/data/metadata_api/Error.json +0 -25
  837. package/skills/getting-metadata-api-context/data/metadata_api/EscalationRules.json +0 -117
  838. package/skills/getting-metadata-api-context/data/metadata_api/EventDelivery.json +0 -57
  839. package/skills/getting-metadata-api-context/data/metadata_api/EventRelayConfig.json +0 -55
  840. package/skills/getting-metadata-api-context/data/metadata_api/EventSettings.json +0 -76
  841. package/skills/getting-metadata-api-context/data/metadata_api/EventSubscription.json +0 -62
  842. package/skills/getting-metadata-api-context/data/metadata_api/ExperienceBundle.json +0 -387
  843. package/skills/getting-metadata-api-context/data/metadata_api/ExperienceBundleSettings.json +0 -25
  844. package/skills/getting-metadata-api-context/data/metadata_api/ExperiencePropertyTypeBundle.json +0 -68
  845. package/skills/getting-metadata-api-context/data/metadata_api/ExplainabilityMsgTemplate.json +0 -56
  846. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetDefinition.json +0 -496
  847. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetMessageToken.json +0 -42
  848. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetObjectAlias.json +0 -61
  849. package/skills/getting-metadata-api-context/data/metadata_api/ExternalAIModel.json +0 -54
  850. package/skills/getting-metadata-api-context/data/metadata_api/ExternalAuthIdentityProvider.json +0 -79
  851. package/skills/getting-metadata-api-context/data/metadata_api/ExternalClientAppSettings.json +0 -40
  852. package/skills/getting-metadata-api-context/data/metadata_api/ExternalClientApplication.json +0 -72
  853. package/skills/getting-metadata-api-context/data/metadata_api/ExternalCredential.json +0 -94
  854. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataConnector.json +0 -51
  855. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataSource.json +0 -162
  856. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTranObject.json +0 -191
  857. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTransportFieldTemplate.json +0 -8
  858. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTransportObjectTemplate.json +0 -8
  859. package/skills/getting-metadata-api-context/data/metadata_api/ExternalServiceRegistration.json +0 -121
  860. package/skills/getting-metadata-api-context/data/metadata_api/ExternalServicesSettings.json +0 -34
  861. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppCanvasSettings.json +0 -63
  862. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppConfigurablePolicies.json +0 -75
  863. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppGlobalOauthSettings.json +0 -135
  864. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppMobileConfigurablePolicies.json +0 -34
  865. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppMobileSettings.json +0 -35
  866. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppNotificationSettings.json +0 -49
  867. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppOauthConfigurablePolicies.json +0 -153
  868. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppOauthSettings.json +0 -120
  869. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppPushConfigurablePolicies.json +0 -35
  870. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppPushSettings.json +0 -93
  871. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppSamlConfigurablePolicies.json +0 -119
  872. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterBoolean.json +0 -47
  873. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterDate.json +0 -47
  874. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterInteger.json +0 -47
  875. package/skills/getting-metadata-api-context/data/metadata_api/FieldMappingConfig.json +0 -43
  876. package/skills/getting-metadata-api-context/data/metadata_api/FieldRestrictionRule.json +0 -80
  877. package/skills/getting-metadata-api-context/data/metadata_api/FieldServiceSettings.json +0 -226
  878. package/skills/getting-metadata-api-context/data/metadata_api/FieldSet.json +0 -60
  879. package/skills/getting-metadata-api-context/data/metadata_api/FieldSrcTrgtRelationship.json +0 -56
  880. package/skills/getting-metadata-api-context/data/metadata_api/FileUploadAndDownloadSecuritySettings.json +0 -53
  881. package/skills/getting-metadata-api-context/data/metadata_api/FilesConnectSettings.json +0 -40
  882. package/skills/getting-metadata-api-context/data/metadata_api/FlexiPage.json +0 -355
  883. package/skills/getting-metadata-api-context/data/metadata_api/Flow.json +0 -2377
  884. package/skills/getting-metadata-api-context/data/metadata_api/FlowCategory.json +0 -51
  885. package/skills/getting-metadata-api-context/data/metadata_api/FlowDefinition.json +0 -37
  886. package/skills/getting-metadata-api-context/data/metadata_api/FlowSettings.json +0 -124
  887. package/skills/getting-metadata-api-context/data/metadata_api/FlowTest.json +0 -205
  888. package/skills/getting-metadata-api-context/data/metadata_api/FlowValueMap.json +0 -68
  889. package/skills/getting-metadata-api-context/data/metadata_api/Folder.json +0 -50
  890. package/skills/getting-metadata-api-context/data/metadata_api/FolderShare.json +0 -45
  891. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingFilter.json +0 -48
  892. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingFilterCondition.json +0 -62
  893. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingObjectListSettings.json +0 -77
  894. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingSettings.json +0 -303
  895. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingSourceDefinition.json +0 -62
  896. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingType.json +0 -100
  897. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingTypeSource.json +0 -60
  898. package/skills/getting-metadata-api-context/data/metadata_api/FuelType.json +0 -52
  899. package/skills/getting-metadata-api-context/data/metadata_api/FuelTypeSustnUom.json +0 -45
  900. package/skills/getting-metadata-api-context/data/metadata_api/FunctionReference.json +0 -31
  901. package/skills/getting-metadata-api-context/data/metadata_api/FundraisingConfig.json +0 -86
  902. package/skills/getting-metadata-api-context/data/metadata_api/GatewayProviderPaymentMethodType.json +0 -50
  903. package/skills/getting-metadata-api-context/data/metadata_api/GenAiFunction.json +0 -171
  904. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlanner.json +0 -215
  905. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlannerBundle.json +0 -220
  906. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlugin.json +0 -87
  907. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPluginInstructionDef.json +0 -42
  908. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPromptTemplate.json +0 -183
  909. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPromptTemplateActv.json +0 -42
  910. package/skills/getting-metadata-api-context/data/metadata_api/GiftEntryGridTemplate.json +0 -42
  911. package/skills/getting-metadata-api-context/data/metadata_api/GlobalPicklist.json +0 -43
  912. package/skills/getting-metadata-api-context/data/metadata_api/GlobalPicklistValue.json +0 -81
  913. package/skills/getting-metadata-api-context/data/metadata_api/GlobalValueSet.json +0 -46
  914. package/skills/getting-metadata-api-context/data/metadata_api/GlobalValueSetTranslation.json +0 -44
  915. package/skills/getting-metadata-api-context/data/metadata_api/GoogleAppsSettings.json +0 -56
  916. package/skills/getting-metadata-api-context/data/metadata_api/Group.json +0 -46
  917. package/skills/getting-metadata-api-context/data/metadata_api/HighVelocitySalesSettings.json +0 -96
  918. package/skills/getting-metadata-api-context/data/metadata_api/HistoryRetentionPolicy.json +0 -41
  919. package/skills/getting-metadata-api-context/data/metadata_api/HomePageComponent.json +0 -66
  920. package/skills/getting-metadata-api-context/data/metadata_api/HomePageLayout.json +0 -40
  921. package/skills/getting-metadata-api-context/data/metadata_api/IPAddressRange.json +0 -60
  922. package/skills/getting-metadata-api-context/data/metadata_api/IdeasSettings.json +0 -52
  923. package/skills/getting-metadata-api-context/data/metadata_api/IdentityProviderSettings.json +0 -39
  924. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcDef.json +0 -173
  925. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcDtl.json +0 -136
  926. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcFld.json +0 -76
  927. package/skills/getting-metadata-api-context/data/metadata_api/IframeWhiteListUrlSettings.json +0 -46
  928. package/skills/getting-metadata-api-context/data/metadata_api/InboundCertificate.json +0 -48
  929. package/skills/getting-metadata-api-context/data/metadata_api/InboundNetworkConnection.json +0 -72
  930. package/skills/getting-metadata-api-context/data/metadata_api/IncidentMgmtSettings.json +0 -140
  931. package/skills/getting-metadata-api-context/data/metadata_api/Index.json +0 -48
  932. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesEinsteinFeatureSettings.json +0 -34
  933. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesLoyaltySettings.json +0 -108
  934. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesPricingSettings.json +0 -61
  935. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesRatingSettings.json +0 -40
  936. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesSettings.json +0 -731
  937. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesUnifiedInventorySettings.json +0 -40
  938. package/skills/getting-metadata-api-context/data/metadata_api/InsPlcyLimitConsumptionRule.json +0 -46
  939. package/skills/getting-metadata-api-context/data/metadata_api/InstalledPackage.json +0 -46
  940. package/skills/getting-metadata-api-context/data/metadata_api/IntegArtifactDef.json +0 -10
  941. package/skills/getting-metadata-api-context/data/metadata_api/IntegrationProviderDef.json +0 -155
  942. package/skills/getting-metadata-api-context/data/metadata_api/InterestTaggingSettings.json +0 -32
  943. package/skills/getting-metadata-api-context/data/metadata_api/InternalDataConnector.json +0 -8
  944. package/skills/getting-metadata-api-context/data/metadata_api/InvLatePymntRiskCalcSettings.json +0 -32
  945. package/skills/getting-metadata-api-context/data/metadata_api/InventorySettings.json +0 -36
  946. package/skills/getting-metadata-api-context/data/metadata_api/InvocableActionExtension.json +0 -84
  947. package/skills/getting-metadata-api-context/data/metadata_api/InvocableActionSettings.json +0 -28
  948. package/skills/getting-metadata-api-context/data/metadata_api/KeywordList.json +0 -51
  949. package/skills/getting-metadata-api-context/data/metadata_api/KnowledgeSettings.json +0 -280
  950. package/skills/getting-metadata-api-context/data/metadata_api/LanguageSettings.json +0 -68
  951. package/skills/getting-metadata-api-context/data/metadata_api/Layout.json +0 -659
  952. package/skills/getting-metadata-api-context/data/metadata_api/LeadConfigSettings.json +0 -64
  953. package/skills/getting-metadata-api-context/data/metadata_api/LeadConvertSettings.json +0 -71
  954. package/skills/getting-metadata-api-context/data/metadata_api/LearningItemType.json +0 -65
  955. package/skills/getting-metadata-api-context/data/metadata_api/Letterhead.json +0 -119
  956. package/skills/getting-metadata-api-context/data/metadata_api/LightningBolt.json +0 -103
  957. package/skills/getting-metadata-api-context/data/metadata_api/LightningComponentBundle.json +0 -109
  958. package/skills/getting-metadata-api-context/data/metadata_api/LightningExperienceSettings.json +0 -191
  959. package/skills/getting-metadata-api-context/data/metadata_api/LightningExperienceTheme.json +0 -54
  960. package/skills/getting-metadata-api-context/data/metadata_api/LightningMessageChannel.json +0 -63
  961. package/skills/getting-metadata-api-context/data/metadata_api/LightningOnboardingConfig.json +0 -62
  962. package/skills/getting-metadata-api-context/data/metadata_api/LightningTypeBundle.json +0 -88
  963. package/skills/getting-metadata-api-context/data/metadata_api/ListMetadataQuery.json +0 -10
  964. package/skills/getting-metadata-api-context/data/metadata_api/ListView.json +0 -86
  965. package/skills/getting-metadata-api-context/data/metadata_api/LiveAgentSettings.json +0 -44
  966. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatAgentConfig.json +0 -188
  967. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatButton.json +0 -188
  968. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatDeployment.json +0 -81
  969. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatSensitiveDataRule.json +0 -56
  970. package/skills/getting-metadata-api-context/data/metadata_api/LiveMessageSettings.json +0 -36
  971. package/skills/getting-metadata-api-context/data/metadata_api/LoyaltyProgramSetup.json +0 -297
  972. package/skills/getting-metadata-api-context/data/metadata_api/MLDataDefinition.json +0 -146
  973. package/skills/getting-metadata-api-context/data/metadata_api/MLPredictionDefinition.json +0 -67
  974. package/skills/getting-metadata-api-context/data/metadata_api/MacroSettings.json +0 -36
  975. package/skills/getting-metadata-api-context/data/metadata_api/MailMergeSettings.json +0 -36
  976. package/skills/getting-metadata-api-context/data/metadata_api/ManagedContentType.json +0 -86
  977. package/skills/getting-metadata-api-context/data/metadata_api/ManagedEventSubscription.json +0 -52
  978. package/skills/getting-metadata-api-context/data/metadata_api/ManagedTopics.json +0 -57
  979. package/skills/getting-metadata-api-context/data/metadata_api/MapAndLocationSettings.json +0 -34
  980. package/skills/getting-metadata-api-context/data/metadata_api/MarketSegmentDefinition.json +0 -58
  981. package/skills/getting-metadata-api-context/data/metadata_api/MarketingAppExtension.json +0 -139
  982. package/skills/getting-metadata-api-context/data/metadata_api/MatchingRule.json +0 -69
  983. package/skills/getting-metadata-api-context/data/metadata_api/MeetingsSettings.json +0 -36
  984. package/skills/getting-metadata-api-context/data/metadata_api/MessagingChannel.json +0 -278
  985. package/skills/getting-metadata-api-context/data/metadata_api/MetadataWithContent.json +0 -24
  986. package/skills/getting-metadata-api-context/data/metadata_api/Metadata_Type_Limits.json +0 -8
  987. package/skills/getting-metadata-api-context/data/metadata_api/MfgProgramTemplate.json +0 -88
  988. package/skills/getting-metadata-api-context/data/metadata_api/MfgServiceConsoleSettings.json +0 -32
  989. package/skills/getting-metadata-api-context/data/metadata_api/MilestoneType.json +0 -36
  990. package/skills/getting-metadata-api-context/data/metadata_api/MktCalcInsightObjectDef.json +0 -54
  991. package/skills/getting-metadata-api-context/data/metadata_api/MktDataTranObject.json +0 -99
  992. package/skills/getting-metadata-api-context/data/metadata_api/MlDomain.json +0 -136
  993. package/skills/getting-metadata-api-context/data/metadata_api/MobSecurityCertPinConfig.json +0 -76
  994. package/skills/getting-metadata-api-context/data/metadata_api/MobileApplicationDetail.json +0 -71
  995. package/skills/getting-metadata-api-context/data/metadata_api/MobileSecurityAssignment.json +0 -44
  996. package/skills/getting-metadata-api-context/data/metadata_api/MobileSecurityPolicy.json +0 -75
  997. package/skills/getting-metadata-api-context/data/metadata_api/MobileSettings.json +0 -121
  998. package/skills/getting-metadata-api-context/data/metadata_api/ModerationRule.json +0 -99
  999. package/skills/getting-metadata-api-context/data/metadata_api/MutingPermissionSet.json +0 -33
  1000. package/skills/getting-metadata-api-context/data/metadata_api/MyDomainDiscoverableLogin.json +0 -41
  1001. package/skills/getting-metadata-api-context/data/metadata_api/MyDomainSettings.json +0 -140
  1002. package/skills/getting-metadata-api-context/data/metadata_api/NameSettings.json +0 -40
  1003. package/skills/getting-metadata-api-context/data/metadata_api/NamedCredential.json +0 -205
  1004. package/skills/getting-metadata-api-context/data/metadata_api/NamedFilter.json +0 -89
  1005. package/skills/getting-metadata-api-context/data/metadata_api/NavigationMenu.json +0 -101
  1006. package/skills/getting-metadata-api-context/data/metadata_api/Network.json +0 -606
  1007. package/skills/getting-metadata-api-context/data/metadata_api/NetworkBranding.json +0 -117
  1008. package/skills/getting-metadata-api-context/data/metadata_api/NotificationTypeConfig.json +0 -75
  1009. package/skills/getting-metadata-api-context/data/metadata_api/NotificationsSettings.json +0 -40
  1010. package/skills/getting-metadata-api-context/data/metadata_api/OauthCustomScope.json +0 -56
  1011. package/skills/getting-metadata-api-context/data/metadata_api/OauthOidcSettings.json +0 -52
  1012. package/skills/getting-metadata-api-context/data/metadata_api/OauthTokenExchangeHandler.json +0 -119
  1013. package/skills/getting-metadata-api-context/data/metadata_api/ObjectHierarchyRelationship.json +0 -108
  1014. package/skills/getting-metadata-api-context/data/metadata_api/ObjectLinkingSettings.json +0 -32
  1015. package/skills/getting-metadata-api-context/data/metadata_api/ObjectSourceTargetMap.json +0 -85
  1016. package/skills/getting-metadata-api-context/data/metadata_api/OcrSampleDocument.json +0 -158
  1017. package/skills/getting-metadata-api-context/data/metadata_api/OcrTemplate.json +0 -180
  1018. package/skills/getting-metadata-api-context/data/metadata_api/OmniChannelSettings.json +0 -48
  1019. package/skills/getting-metadata-api-context/data/metadata_api/OmniExtTrackingDef.json +0 -66
  1020. package/skills/getting-metadata-api-context/data/metadata_api/OmniInteractionAccessConfig.json +0 -90
  1021. package/skills/getting-metadata-api-context/data/metadata_api/OmniInteractionConfig.json +0 -37
  1022. package/skills/getting-metadata-api-context/data/metadata_api/OmniScript.json +0 -204
  1023. package/skills/getting-metadata-api-context/data/metadata_api/OmniSupervisorConfig.json +0 -156
  1024. package/skills/getting-metadata-api-context/data/metadata_api/OmniTrackingGroup.json +0 -77
  1025. package/skills/getting-metadata-api-context/data/metadata_api/OnboardingDataObjectGroup.json +0 -131
  1026. package/skills/getting-metadata-api-context/data/metadata_api/OpportunityInsightsSettings.json +0 -30
  1027. package/skills/getting-metadata-api-context/data/metadata_api/OpportunityScoreSettings.json +0 -32
  1028. package/skills/getting-metadata-api-context/data/metadata_api/OpportunitySettings.json +0 -132
  1029. package/skills/getting-metadata-api-context/data/metadata_api/OrchestrationPlanCtxMapping.json +0 -63
  1030. package/skills/getting-metadata-api-context/data/metadata_api/OrderManagementSettings.json +0 -52
  1031. package/skills/getting-metadata-api-context/data/metadata_api/OrderSettings.json +0 -60
  1032. package/skills/getting-metadata-api-context/data/metadata_api/OrgPreferenceSettings.json +0 -43
  1033. package/skills/getting-metadata-api-context/data/metadata_api/OrgSettings.json +0 -40
  1034. package/skills/getting-metadata-api-context/data/metadata_api/OutboundNetworkConnection.json +0 -71
  1035. package/skills/getting-metadata-api-context/data/metadata_api/OwnerSharingRule.json +0 -206
  1036. package/skills/getting-metadata-api-context/data/metadata_api/Package.json +0 -19
  1037. package/skills/getting-metadata-api-context/data/metadata_api/PardotEinsteinSettings.json +0 -36
  1038. package/skills/getting-metadata-api-context/data/metadata_api/PardotSettings.json +0 -72
  1039. package/skills/getting-metadata-api-context/data/metadata_api/ParticipantRole.json +0 -48
  1040. package/skills/getting-metadata-api-context/data/metadata_api/PartyDataModelSettings.json +0 -40
  1041. package/skills/getting-metadata-api-context/data/metadata_api/PathAssistant.json +0 -74
  1042. package/skills/getting-metadata-api-context/data/metadata_api/PathAssistantSettings.json +0 -40
  1043. package/skills/getting-metadata-api-context/data/metadata_api/PaymentGatewayProvider.json +0 -50
  1044. package/skills/getting-metadata-api-context/data/metadata_api/PaymentsSettings.json +0 -32
  1045. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSet.json +0 -372
  1046. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSetGroup.json +0 -57
  1047. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSetLicenseDefinition.json +0 -58
  1048. package/skills/getting-metadata-api-context/data/metadata_api/PersonAccountOwnerPowerUser.json +0 -38
  1049. package/skills/getting-metadata-api-context/data/metadata_api/Picklist.json +0 -43
  1050. package/skills/getting-metadata-api-context/data/metadata_api/PicklistSettings.json +0 -32
  1051. package/skills/getting-metadata-api-context/data/metadata_api/PipelineInspMetricConfig.json +0 -48
  1052. package/skills/getting-metadata-api-context/data/metadata_api/PlatformCachePartition.json +0 -79
  1053. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEncryptionSettings.json +0 -51
  1054. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventChannel.json +0 -56
  1055. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventChannelMember.json +0 -71
  1056. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventMigration.json +0 -39
  1057. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventSettings.json +0 -32
  1058. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventSubscriberConfig.json +0 -58
  1059. package/skills/getting-metadata-api-context/data/metadata_api/Portal.json +0 -137
  1060. package/skills/getting-metadata-api-context/data/metadata_api/PortalDelegablePermissionSet.json +0 -48
  1061. package/skills/getting-metadata-api-context/data/metadata_api/PostTemplate.json +0 -47
  1062. package/skills/getting-metadata-api-context/data/metadata_api/PredictionBuilderSettings.json +0 -36
  1063. package/skills/getting-metadata-api-context/data/metadata_api/PresenceDeclineReason.json +0 -32
  1064. package/skills/getting-metadata-api-context/data/metadata_api/PresenceUserConfig.json +0 -122
  1065. package/skills/getting-metadata-api-context/data/metadata_api/PricingActionParameters.json +0 -64
  1066. package/skills/getting-metadata-api-context/data/metadata_api/PricingRecipe.json +0 -117
  1067. package/skills/getting-metadata-api-context/data/metadata_api/PrivacySettings.json +0 -80
  1068. package/skills/getting-metadata-api-context/data/metadata_api/ProcessFlowMigration.json +0 -58
  1069. package/skills/getting-metadata-api-context/data/metadata_api/ProductAttributeSet.json +0 -33
  1070. package/skills/getting-metadata-api-context/data/metadata_api/ProductSettings.json +0 -44
  1071. package/skills/getting-metadata-api-context/data/metadata_api/Profile.json +0 -492
  1072. package/skills/getting-metadata-api-context/data/metadata_api/ProfileActionOverride.json +0 -48
  1073. package/skills/getting-metadata-api-context/data/metadata_api/ProfilePasswordPolicy.json +0 -80
  1074. package/skills/getting-metadata-api-context/data/metadata_api/ProfileSearchLayouts.json +0 -32
  1075. package/skills/getting-metadata-api-context/data/metadata_api/ProfileSessionSetting.json +0 -55
  1076. package/skills/getting-metadata-api-context/data/metadata_api/Prompt.json +0 -255
  1077. package/skills/getting-metadata-api-context/data/metadata_api/PublicKeyCertificate.json +0 -50
  1078. package/skills/getting-metadata-api-context/data/metadata_api/PublicKeyCertificateSet.json +0 -65
  1079. package/skills/getting-metadata-api-context/data/metadata_api/Queue.json +0 -123
  1080. package/skills/getting-metadata-api-context/data/metadata_api/QueueRoutingConfig.json +0 -96
  1081. package/skills/getting-metadata-api-context/data/metadata_api/QuickAction.json +0 -175
  1082. package/skills/getting-metadata-api-context/data/metadata_api/QuoteSettings.json +0 -36
  1083. package/skills/getting-metadata-api-context/data/metadata_api/ReadResult.json +0 -16
  1084. package/skills/getting-metadata-api-context/data/metadata_api/RealTimeEventSettings.json +0 -45
  1085. package/skills/getting-metadata-api-context/data/metadata_api/RecommendationStrategy.json +0 -327
  1086. package/skills/getting-metadata-api-context/data/metadata_api/RecordActionDeployment.json +0 -184
  1087. package/skills/getting-metadata-api-context/data/metadata_api/RecordAggregationDefinition.json +0 -148
  1088. package/skills/getting-metadata-api-context/data/metadata_api/RecordAlertCategory.json +0 -42
  1089. package/skills/getting-metadata-api-context/data/metadata_api/RecordPageSettings.json +0 -40
  1090. package/skills/getting-metadata-api-context/data/metadata_api/RecordType.json +0 -68
  1091. package/skills/getting-metadata-api-context/data/metadata_api/RedirectWhitelistUrl.json +0 -26
  1092. package/skills/getting-metadata-api-context/data/metadata_api/ReferencedDashboard.json +0 -55
  1093. package/skills/getting-metadata-api-context/data/metadata_api/RegisteredExternalService.json +0 -72
  1094. package/skills/getting-metadata-api-context/data/metadata_api/RelatedRecordAssocCriteria.json +0 -75
  1095. package/skills/getting-metadata-api-context/data/metadata_api/RelationshipGraphDefinition.json +0 -63
  1096. package/skills/getting-metadata-api-context/data/metadata_api/RemoteSiteSetting.json +0 -51
  1097. package/skills/getting-metadata-api-context/data/metadata_api/Report.json +0 -715
  1098. package/skills/getting-metadata-api-context/data/metadata_api/ReportType.json +0 -118
  1099. package/skills/getting-metadata-api-context/data/metadata_api/RestrictionRule.json +0 -71
  1100. package/skills/getting-metadata-api-context/data/metadata_api/RetailExecutionSettings.json +0 -40
  1101. package/skills/getting-metadata-api-context/data/metadata_api/RetrievalSummaryDefinition.json +0 -76
  1102. package/skills/getting-metadata-api-context/data/metadata_api/RetrieveRequest.json +0 -35
  1103. package/skills/getting-metadata-api-context/data/metadata_api/RetrieveResult.json +0 -103
  1104. package/skills/getting-metadata-api-context/data/metadata_api/Role.json +0 -35
  1105. package/skills/getting-metadata-api-context/data/metadata_api/RoleOrTerritory.json +0 -57
  1106. package/skills/getting-metadata-api-context/data/metadata_api/SalesAgreementSettings.json +0 -180
  1107. package/skills/getting-metadata-api-context/data/metadata_api/SalesWorkQueueSettings.json +0 -40
  1108. package/skills/getting-metadata-api-context/data/metadata_api/SamlSsoConfig.json +0 -128
  1109. package/skills/getting-metadata-api-context/data/metadata_api/SandboxSettings.json +0 -32
  1110. package/skills/getting-metadata-api-context/data/metadata_api/SaveResult.json +0 -22
  1111. package/skills/getting-metadata-api-context/data/metadata_api/SchedulingObjective.json +0 -66
  1112. package/skills/getting-metadata-api-context/data/metadata_api/SchedulingRule.json +0 -66
  1113. package/skills/getting-metadata-api-context/data/metadata_api/SchemaSettings.json +0 -44
  1114. package/skills/getting-metadata-api-context/data/metadata_api/Scontrol.json +0 -72
  1115. package/skills/getting-metadata-api-context/data/metadata_api/SearchCustomization.json +0 -120
  1116. package/skills/getting-metadata-api-context/data/metadata_api/SearchLayouts.json +0 -64
  1117. package/skills/getting-metadata-api-context/data/metadata_api/SearchOrgWideObjectConfig.json +0 -61
  1118. package/skills/getting-metadata-api-context/data/metadata_api/SearchSettings.json +0 -155
  1119. package/skills/getting-metadata-api-context/data/metadata_api/SecuritySettings.json +0 -437
  1120. package/skills/getting-metadata-api-context/data/metadata_api/ServiceAISetupDefinition.json +0 -48
  1121. package/skills/getting-metadata-api-context/data/metadata_api/ServiceAISetupField.json +0 -58
  1122. package/skills/getting-metadata-api-context/data/metadata_api/ServiceChannel.json +0 -123
  1123. package/skills/getting-metadata-api-context/data/metadata_api/ServiceCloudVoiceSettings.json +0 -83
  1124. package/skills/getting-metadata-api-context/data/metadata_api/ServicePresenceStatus.json +0 -45
  1125. package/skills/getting-metadata-api-context/data/metadata_api/ServiceProcess.json +0 -141
  1126. package/skills/getting-metadata-api-context/data/metadata_api/ServiceSetupAssistantSettings.json +0 -32
  1127. package/skills/getting-metadata-api-context/data/metadata_api/SessionHeader.json +0 -17
  1128. package/skills/getting-metadata-api-context/data/metadata_api/SharedTo.json +0 -105
  1129. package/skills/getting-metadata-api-context/data/metadata_api/SharingBaseRule.json +0 -60
  1130. package/skills/getting-metadata-api-context/data/metadata_api/SharingReason.json +0 -34
  1131. package/skills/getting-metadata-api-context/data/metadata_api/SharingRecalculation.json +0 -29
  1132. package/skills/getting-metadata-api-context/data/metadata_api/SharingRules.json +0 -186
  1133. package/skills/getting-metadata-api-context/data/metadata_api/SharingSet.json +0 -78
  1134. package/skills/getting-metadata-api-context/data/metadata_api/SharingSettings.json +0 -92
  1135. package/skills/getting-metadata-api-context/data/metadata_api/SiteDotCom.json +0 -37
  1136. package/skills/getting-metadata-api-context/data/metadata_api/SiteSettings.json +0 -60
  1137. package/skills/getting-metadata-api-context/data/metadata_api/Skill.json +0 -69
  1138. package/skills/getting-metadata-api-context/data/metadata_api/SocialCustomerServiceSettings.json +0 -61
  1139. package/skills/getting-metadata-api-context/data/metadata_api/SocialProfileSettings.json +0 -35
  1140. package/skills/getting-metadata-api-context/data/metadata_api/SourceTrackingSettings.json +0 -32
  1141. package/skills/getting-metadata-api-context/data/metadata_api/StageAssignment.json +0 -113
  1142. package/skills/getting-metadata-api-context/data/metadata_api/StageDefinition.json +0 -237
  1143. package/skills/getting-metadata-api-context/data/metadata_api/StandardValueSet.json +0 -41
  1144. package/skills/getting-metadata-api-context/data/metadata_api/StandardValueSetTranslation.json +0 -32
  1145. package/skills/getting-metadata-api-context/data/metadata_api/StaticResource.json +0 -49
  1146. package/skills/getting-metadata-api-context/data/metadata_api/StreamingAppDataConnector.json +0 -51
  1147. package/skills/getting-metadata-api-context/data/metadata_api/SubscriptionManagementSettings.json +0 -56
  1148. package/skills/getting-metadata-api-context/data/metadata_api/SurveySettings.json +0 -44
  1149. package/skills/getting-metadata-api-context/data/metadata_api/SustainabilityUom.json +0 -61
  1150. package/skills/getting-metadata-api-context/data/metadata_api/SustnUomConversion.json +0 -58
  1151. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogCategory.json +0 -54
  1152. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogFulfillmentFlow.json +0 -99
  1153. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogItemDef.json +0 -202
  1154. package/skills/getting-metadata-api-context/data/metadata_api/SynonymDictionary.json +0 -56
  1155. package/skills/getting-metadata-api-context/data/metadata_api/Tag.json +0 -70
  1156. package/skills/getting-metadata-api-context/data/metadata_api/TagSet.json +0 -47
  1157. package/skills/getting-metadata-api-context/data/metadata_api/Territory.json +0 -39
  1158. package/skills/getting-metadata-api-context/data/metadata_api/Territory2.json +0 -112
  1159. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Model.json +0 -41
  1160. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Rule.json +0 -68
  1161. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Settings.json +0 -111
  1162. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Type.json +0 -42
  1163. package/skills/getting-metadata-api-context/data/metadata_api/TimeSheetTemplate.json +0 -75
  1164. package/skills/getting-metadata-api-context/data/metadata_api/TimelineObjectDefinition.json +0 -48
  1165. package/skills/getting-metadata-api-context/data/metadata_api/TopicsForObjects.json +0 -38
  1166. package/skills/getting-metadata-api-context/data/metadata_api/TrailheadSettings.json +0 -40
  1167. package/skills/getting-metadata-api-context/data/metadata_api/TransactionSecurityPolicy.json +0 -127
  1168. package/skills/getting-metadata-api-context/data/metadata_api/Translations.json +0 -976
  1169. package/skills/getting-metadata-api-context/data/metadata_api/TrialOrgSettings.json +0 -32
  1170. package/skills/getting-metadata-api-context/data/metadata_api/UIBundle.json +0 -54
  1171. package/skills/getting-metadata-api-context/data/metadata_api/UIObjectRelationConfig.json +0 -101
  1172. package/skills/getting-metadata-api-context/data/metadata_api/UiFormatSpecificationSet.json +0 -103
  1173. package/skills/getting-metadata-api-context/data/metadata_api/UiPreviewMessageTabDef.json +0 -70
  1174. package/skills/getting-metadata-api-context/data/metadata_api/UpsertResult.json +0 -25
  1175. package/skills/getting-metadata-api-context/data/metadata_api/UserAccessPolicy.json +0 -120
  1176. package/skills/getting-metadata-api-context/data/metadata_api/UserAuthCertificate.json +0 -57
  1177. package/skills/getting-metadata-api-context/data/metadata_api/UserCriteria.json +0 -48
  1178. package/skills/getting-metadata-api-context/data/metadata_api/UserEngagementSettings.json +0 -136
  1179. package/skills/getting-metadata-api-context/data/metadata_api/UserInterfaceSettings.json +0 -96
  1180. package/skills/getting-metadata-api-context/data/metadata_api/UserManagementSettings.json +0 -108
  1181. package/skills/getting-metadata-api-context/data/metadata_api/UserProfileSearchScope.json +0 -8
  1182. package/skills/getting-metadata-api-context/data/metadata_api/UserProvisioningConfig.json +0 -72
  1183. package/skills/getting-metadata-api-context/data/metadata_api/ValidationRule.json +0 -51
  1184. package/skills/getting-metadata-api-context/data/metadata_api/VirtualVisitConfig.json +0 -97
  1185. package/skills/getting-metadata-api-context/data/metadata_api/VoiceSettings.json +0 -68
  1186. package/skills/getting-metadata-api-context/data/metadata_api/WarrantyLifeCycleMgmtSettings.json +0 -32
  1187. package/skills/getting-metadata-api-context/data/metadata_api/WaveAnalyticAssetCollection.json +0 -73
  1188. package/skills/getting-metadata-api-context/data/metadata_api/WaveApplication.json +0 -56
  1189. package/skills/getting-metadata-api-context/data/metadata_api/WaveComponent.json +0 -46
  1190. package/skills/getting-metadata-api-context/data/metadata_api/WaveDashboard.json +0 -50
  1191. package/skills/getting-metadata-api-context/data/metadata_api/WaveDataflow.json +0 -45
  1192. package/skills/getting-metadata-api-context/data/metadata_api/WaveDataset.json +0 -50
  1193. package/skills/getting-metadata-api-context/data/metadata_api/WaveLens.json +0 -59
  1194. package/skills/getting-metadata-api-context/data/metadata_api/WaveRecipe.json +0 -58
  1195. package/skills/getting-metadata-api-context/data/metadata_api/WaveTemplateBundle.json +0 -37
  1196. package/skills/getting-metadata-api-context/data/metadata_api/WaveXmd.json +0 -567
  1197. package/skills/getting-metadata-api-context/data/metadata_api/WebLink.json +0 -117
  1198. package/skills/getting-metadata-api-context/data/metadata_api/WebStoreBundle.json +0 -10
  1199. package/skills/getting-metadata-api-context/data/metadata_api/WebStoreTemplate.json +0 -166
  1200. package/skills/getting-metadata-api-context/data/metadata_api/WorkDotComSettings.json +0 -76
  1201. package/skills/getting-metadata-api-context/data/metadata_api/WorkSkillRouting.json +0 -76
  1202. package/skills/getting-metadata-api-context/data/metadata_api/Workflow.json +0 -415
  1203. package/skills/getting-metadata-api-context/data/metadata_api/WorkforceEngagementSettings.json +0 -56
  1204. package/skills/getting-metadata-api-context/examples/README.md +0 -169
  1205. package/skills/getting-metadata-api-context/examples/bash_section_loading.sh +0 -142
  1206. package/skills/getting-metadata-api-context/examples/javascript_section_loading.js +0 -162
  1207. package/skills/getting-metadata-api-context/examples/python_section_loading.py +0 -112
  1208. package/skills/getting-metadata-api-context/references/metadata_index_table.md +0 -654
  1209. package/skills/getting-metadata-api-context/references/usage_guide.md +0 -420
  1210. package/skills/handling-sf-data/CREDITS.md +0 -5
  1211. package/skills/handling-sf-data/README.md +0 -112
  1212. package/skills/handling-sf-data/SKILL.md +0 -234
  1213. package/skills/handling-sf-data/assets/bulk/bulk-insert-10000.apex +0 -293
  1214. package/skills/handling-sf-data/assets/bulk/bulk-insert-200.apex +0 -208
  1215. package/skills/handling-sf-data/assets/bulk/bulk-insert-500.apex +0 -219
  1216. package/skills/handling-sf-data/assets/bulk/bulk-upsert-external-id.apex +0 -324
  1217. package/skills/handling-sf-data/assets/cleanup/delete-by-created-date.apex +0 -319
  1218. package/skills/handling-sf-data/assets/cleanup/delete-by-name.apex +0 -240
  1219. package/skills/handling-sf-data/assets/cleanup/delete-test-data.apex +0 -311
  1220. package/skills/handling-sf-data/assets/cleanup/rollback-transaction.apex +0 -266
  1221. package/skills/handling-sf-data/assets/csv/account-import.csv +0 -11
  1222. package/skills/handling-sf-data/assets/csv/contact-import.csv +0 -11
  1223. package/skills/handling-sf-data/assets/csv/custom-object-import.csv +0 -11
  1224. package/skills/handling-sf-data/assets/csv/opportunity-import.csv +0 -11
  1225. package/skills/handling-sf-data/assets/factories/account-factory.apex +0 -165
  1226. package/skills/handling-sf-data/assets/factories/case-factory.apex +0 -237
  1227. package/skills/handling-sf-data/assets/factories/contact-factory.apex +0 -168
  1228. package/skills/handling-sf-data/assets/factories/custom-object-factory.apex +0 -260
  1229. package/skills/handling-sf-data/assets/factories/event-factory.apex +0 -275
  1230. package/skills/handling-sf-data/assets/factories/hierarchy-factory.apex +0 -372
  1231. package/skills/handling-sf-data/assets/factories/lead-factory.apex +0 -190
  1232. package/skills/handling-sf-data/assets/factories/opportunity-factory.apex +0 -206
  1233. package/skills/handling-sf-data/assets/factories/task-factory.apex +0 -246
  1234. package/skills/handling-sf-data/assets/factories/user-factory.apex +0 -278
  1235. package/skills/handling-sf-data/assets/json/account-contact-tree.json +0 -130
  1236. package/skills/handling-sf-data/assets/json/account-opportunity-tree.json +0 -110
  1237. package/skills/handling-sf-data/assets/json/full-hierarchy-tree.json +0 -188
  1238. package/skills/handling-sf-data/assets/soql/aggregate.soql +0 -226
  1239. package/skills/handling-sf-data/assets/soql/child-to-parent.soql +0 -162
  1240. package/skills/handling-sf-data/assets/soql/parent-to-child.soql +0 -153
  1241. package/skills/handling-sf-data/assets/soql/polymorphic.soql +0 -198
  1242. package/skills/handling-sf-data/assets/soql/subquery.soql +0 -287
  1243. package/skills/handling-sf-data/references/anonymous-apex-guide.md +0 -98
  1244. package/skills/handling-sf-data/references/bulk-operations-guide.md +0 -94
  1245. package/skills/handling-sf-data/references/bulk-testing-example.md +0 -194
  1246. package/skills/handling-sf-data/references/cleanup-rollback-example.md +0 -322
  1247. package/skills/handling-sf-data/references/cleanup-rollback-guide.md +0 -84
  1248. package/skills/handling-sf-data/references/crud-workflow-example.md +0 -183
  1249. package/skills/handling-sf-data/references/governor-limits-reference.md +0 -74
  1250. package/skills/handling-sf-data/references/orchestration.md +0 -174
  1251. package/skills/handling-sf-data/references/relationship-query-examples.md +0 -249
  1252. package/skills/handling-sf-data/references/sf-cli-data-commands.md +0 -158
  1253. package/skills/handling-sf-data/references/soql-relationship-guide.md +0 -84
  1254. package/skills/handling-sf-data/references/test-data-best-practices.md +0 -104
  1255. package/skills/handling-sf-data/references/test-data-factory-usage.md +0 -290
  1256. package/skills/handling-sf-data/references/test-data-patterns.md +0 -98
  1257. package/skills/handling-sf-data/scripts/soql_validator.py +0 -292
  1258. package/skills/handling-sf-data/scripts/validate_data_operation.py +0 -379
  1259. package/skills/harmonizing-datacloud/CREDITS.md +0 -3
  1260. package/skills/harmonizing-datacloud/README.md +0 -31
  1261. package/skills/harmonizing-datacloud/SKILL.md +0 -116
  1262. package/skills/implementing-ui-bundle-agentforce-conversation-client/SKILL.md +0 -280
  1263. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/agent-id-resolution.md +0 -46
  1264. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/constraints.md +0 -134
  1265. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/examples.md +0 -132
  1266. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/style-tokens.md +0 -260
  1267. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/troubleshooting.md +0 -57
  1268. package/skills/implementing-ui-bundle-file-upload/SKILL.md +0 -398
  1269. package/skills/integrating-b2b-commerce-open-code-components/SKILL.md +0 -165
  1270. package/skills/investigating-agentforce-architecture/README.md +0 -156
  1271. package/skills/investigating-agentforce-architecture/SKILL.md +0 -230
  1272. package/skills/investigating-agentforce-architecture/assets/cli/describe_sobject.yaml +0 -16
  1273. package/skills/investigating-agentforce-architecture/assets/cli/describe_tooling_sobject.yaml +0 -17
  1274. package/skills/investigating-agentforce-architecture/assets/cli/list_metadata_genaiprompttemplate.yaml +0 -17
  1275. package/skills/investigating-agentforce-architecture/assets/cli/org_display.yaml +0 -15
  1276. package/skills/investigating-agentforce-architecture/assets/cli/retrieve_genai_plugin.yaml +0 -18
  1277. package/skills/investigating-agentforce-architecture/assets/cli/show_access_token.yaml +0 -27
  1278. package/skills/investigating-agentforce-architecture/assets/mermaid/action_tree.mmd +0 -20
  1279. package/skills/investigating-agentforce-architecture/assets/mermaid/data_flow.mmd +0 -19
  1280. package/skills/investigating-agentforce-architecture/assets/mermaid/dependency_graph.mmd +0 -19
  1281. package/skills/investigating-agentforce-architecture/assets/mermaid/invocation_sequence.mmd +0 -20
  1282. package/skills/investigating-agentforce-architecture/assets/mermaid/planner_state.mmd +0 -18
  1283. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_ids.soql +0 -3
  1284. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_names.soql +0 -3
  1285. package/skills/investigating-agentforce-architecture/assets/soql/bot_definition_details.soql +0 -3
  1286. package/skills/investigating-agentforce-architecture/assets/soql/bot_version_lookup.soql +0 -4
  1287. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_by_ids.soql +0 -3
  1288. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_ids_by_names.soql +0 -3
  1289. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_view_by_durable_ids.soql +0 -4
  1290. package/skills/investigating-agentforce-architecture/assets/soql/flow_metadata_by_id.soql +0 -3
  1291. package/skills/investigating-agentforce-architecture/assets/soql/functions_by_plugins.soql +0 -5
  1292. package/skills/investigating-agentforce-architecture/assets/soql/planner_attrs_by_parent_ids.soql +0 -3
  1293. package/skills/investigating-agentforce-architecture/assets/soql/planner_bundle_functions.soql +0 -3
  1294. package/skills/investigating-agentforce-architecture/assets/soql/planner_definition_by_agent_chain.soql +0 -3
  1295. package/skills/investigating-agentforce-architecture/assets/soql/plugin_functions_by_plugin_ids.soql +0 -3
  1296. package/skills/investigating-agentforce-architecture/assets/soql/plugin_instructions_by_plugin_ids.soql +0 -3
  1297. package/skills/investigating-agentforce-architecture/assets/soql/plugins_by_planner.soql +0 -4
  1298. package/skills/investigating-agentforce-architecture/references/architecture_sections.md +0 -243
  1299. package/skills/investigating-agentforce-architecture/references/contract.json +0 -244
  1300. package/skills/investigating-agentforce-architecture/references/soql_fields.md +0 -512
  1301. package/skills/investigating-agentforce-architecture/scripts/_shared/__init__.py +0 -1
  1302. package/skills/investigating-agentforce-architecture/scripts/_shared/fs_guard.py +0 -329
  1303. package/skills/investigating-agentforce-architecture/scripts/_shared/paths.py +0 -110
  1304. package/skills/investigating-agentforce-architecture/scripts/_shared/runtime.py +0 -59
  1305. package/skills/investigating-agentforce-architecture/scripts/_shared/sql.py +0 -10
  1306. package/skills/investigating-agentforce-architecture/scripts/cache_check.py +0 -234
  1307. package/skills/investigating-agentforce-architecture/scripts/config.py +0 -131
  1308. package/skills/investigating-agentforce-architecture/scripts/fetch_soql.py +0 -689
  1309. package/skills/investigating-agentforce-architecture/scripts/finalize.py +0 -295
  1310. package/skills/investigating-agentforce-architecture/scripts/main.py +0 -2835
  1311. package/skills/investigating-agentforce-architecture/scripts/metadata_listing.py +0 -265
  1312. package/skills/investigating-agentforce-architecture/scripts/parallel_retrieve.py +0 -69
  1313. package/skills/investigating-agentforce-architecture/scripts/parse_bundle.py +0 -215
  1314. package/skills/investigating-agentforce-architecture/scripts/parse_wave.py +0 -845
  1315. package/skills/investigating-agentforce-architecture/scripts/probe_channels.py +0 -302
  1316. package/skills/investigating-agentforce-architecture/scripts/render_architecture.py +0 -1043
  1317. package/skills/investigating-agentforce-architecture/scripts/resolve_bot.py +0 -255
  1318. package/skills/investigating-agentforce-architecture/scripts/resolve_invocation_target.py +0 -130
  1319. package/skills/investigating-agentforce-architecture/scripts/rest_client.py +0 -763
  1320. package/skills/investigating-agentforce-architecture/scripts/retrieve_planner.py +0 -13
  1321. package/skills/investigating-agentforce-architecture/scripts/sf_cli.py +0 -242
  1322. package/skills/investigating-agentforce-architecture/scripts/soql_loader.py +0 -253
  1323. package/skills/investigating-agentforce-architecture/scripts/summarize_tree.py +0 -143
  1324. package/skills/investigating-agentforce-architecture/scripts/tests/__init__.py +0 -0
  1325. package/skills/investigating-agentforce-architecture/scripts/tests/_bootstrap.py +0 -23
  1326. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/__init__.py +0 -0
  1327. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/genai_payloads.py +0 -400
  1328. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check.py +0 -307
  1329. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check_main.py +0 -283
  1330. package/skills/investigating-agentforce-architecture/scripts/tests/test_config.py +0 -115
  1331. package/skills/investigating-agentforce-architecture/scripts/tests/test_end_to_end_fixture.py +0 -651
  1332. package/skills/investigating-agentforce-architecture/scripts/tests/test_finalize.py +0 -278
  1333. package/skills/investigating-agentforce-architecture/scripts/tests/test_flow_children_inflation.py +0 -582
  1334. package/skills/investigating-agentforce-architecture/scripts/tests/test_fs_guard.py +0 -113
  1335. package/skills/investigating-agentforce-architecture/scripts/tests/test_iterative_wave_b.py +0 -478
  1336. package/skills/investigating-agentforce-architecture/scripts/tests/test_main_pipeline.py +0 -3359
  1337. package/skills/investigating-agentforce-architecture/scripts/tests/test_parallel_retrieve.py +0 -131
  1338. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_bundle.py +0 -400
  1339. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave.py +0 -644
  1340. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_classifiers.py +0 -224
  1341. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_helpers.py +0 -380
  1342. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_main.py +0 -397
  1343. package/skills/investigating-agentforce-architecture/scripts/tests/test_per_branch_visited.py +0 -244
  1344. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_channels.py +0 -359
  1345. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_cli_recipes.py +0 -185
  1346. package/skills/investigating-agentforce-architecture/scripts/tests/test_render_architecture.py +0 -810
  1347. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_bot.py +0 -203
  1348. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_creds.py +0 -157
  1349. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py +0 -145
  1350. package/skills/investigating-agentforce-architecture/scripts/tests/test_rest_client.py +0 -1253
  1351. package/skills/investigating-agentforce-architecture/scripts/tests/test_runtime_override.py +0 -100
  1352. package/skills/investigating-agentforce-architecture/scripts/tests/test_sf_cli.py +0 -261
  1353. package/skills/investigating-agentforce-architecture/scripts/tests/test_signature_stamping.py +0 -466
  1354. package/skills/investigating-agentforce-architecture/scripts/tests/test_soql_loader.py +0 -501
  1355. package/skills/investigating-agentforce-architecture/scripts/tests/test_summarize_tree.py +0 -241
  1356. package/skills/investigating-agentforce-architecture/scripts/tests/test_write_emit_ctx.py +0 -480
  1357. package/skills/investigating-agentforce-architecture/tools/emit_env.py +0 -157
  1358. package/skills/investigating-agentforce-architecture/tools/emit_result.py +0 -262
  1359. package/skills/investigating-agentforce-architecture/tools/sanitize.py +0 -33
  1360. package/skills/investigating-agentforce-architecture/tools/write_emit_ctx.py +0 -332
  1361. package/skills/investigating-agentforce-d360/README.md +0 -123
  1362. package/skills/investigating-agentforce-d360/SKILL.md +0 -163
  1363. package/skills/investigating-agentforce-d360/assets/dc/app_generation.sql +0 -51
  1364. package/skills/investigating-agentforce-d360/assets/dc/content_category.sql +0 -44
  1365. package/skills/investigating-agentforce-d360/assets/dc/content_quality.sql +0 -41
  1366. package/skills/investigating-agentforce-d360/assets/dc/discover_sessions.sql +0 -36
  1367. package/skills/investigating-agentforce-d360/assets/dc/feedback.sql +0 -47
  1368. package/skills/investigating-agentforce-d360/assets/dc/feedback_details.sql +0 -38
  1369. package/skills/investigating-agentforce-d360/assets/dc/gateway_records.sql +0 -45
  1370. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_llm.sql +0 -50
  1371. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_metadata.sql +0 -44
  1372. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_tags.sql +0 -42
  1373. package/skills/investigating-agentforce-d360/assets/dc/gateway_requests.sql +0 -89
  1374. package/skills/investigating-agentforce-d360/assets/dc/gateway_responses.sql +0 -43
  1375. package/skills/investigating-agentforce-d360/assets/dc/generations.sql +0 -52
  1376. package/skills/investigating-agentforce-d360/assets/dc/interactions.sql +0 -53
  1377. package/skills/investigating-agentforce-d360/assets/dc/messages.sql +0 -53
  1378. package/skills/investigating-agentforce-d360/assets/dc/messaging_session.sql +0 -37
  1379. package/skills/investigating-agentforce-d360/assets/dc/moment_interactions.sql +0 -34
  1380. package/skills/investigating-agentforce-d360/assets/dc/moments.sql +0 -39
  1381. package/skills/investigating-agentforce-d360/assets/dc/participants.sql +0 -48
  1382. package/skills/investigating-agentforce-d360/assets/dc/sessions.sql +0 -78
  1383. package/skills/investigating-agentforce-d360/assets/dc/steps.sql +0 -64
  1384. package/skills/investigating-agentforce-d360/assets/dc/tag_associations.sql +0 -46
  1385. package/skills/investigating-agentforce-d360/assets/dc/tag_definition_associations.sql +0 -37
  1386. package/skills/investigating-agentforce-d360/assets/dc/tag_definitions.sql +0 -50
  1387. package/skills/investigating-agentforce-d360/assets/dc/tags.sql +0 -37
  1388. package/skills/investigating-agentforce-d360/assets/dc/telemetry_spans.sql +0 -55
  1389. package/skills/investigating-agentforce-d360/references/artifacts.md +0 -50
  1390. package/skills/investigating-agentforce-d360/references/dc_dmo_fields.md +0 -823
  1391. package/skills/investigating-agentforce-d360/references/dc_pipeline_contract.md +0 -608
  1392. package/skills/investigating-agentforce-d360/scripts/_shared/__init__.py +0 -2
  1393. package/skills/investigating-agentforce-d360/scripts/_shared/cli_override.py +0 -98
  1394. package/skills/investigating-agentforce-d360/scripts/_shared/fs_guard.py +0 -334
  1395. package/skills/investigating-agentforce-d360/scripts/_shared/paths.py +0 -155
  1396. package/skills/investigating-agentforce-d360/scripts/_shared/runtime.py +0 -59
  1397. package/skills/investigating-agentforce-d360/scripts/_shared/sql.py +0 -14
  1398. package/skills/investigating-agentforce-d360/scripts/assemble_dc.py +0 -1624
  1399. package/skills/investigating-agentforce-d360/scripts/config.py +0 -45
  1400. package/skills/investigating-agentforce-d360/scripts/dc.py +0 -188
  1401. package/skills/investigating-agentforce-d360/scripts/discover_sessions.py +0 -556
  1402. package/skills/investigating-agentforce-d360/scripts/fetch_dc.py +0 -1045
  1403. package/skills/investigating-agentforce-d360/scripts/render_dc.py +0 -1750
  1404. package/skills/investigating-agentforce-d360/scripts/resolve_session.py +0 -264
  1405. package/skills/investigating-agentforce-d360/scripts/storage.py +0 -92
  1406. package/skills/investigating-agentforce-d360/scripts/tests/__init__.py +0 -0
  1407. package/skills/investigating-agentforce-d360/scripts/tests/_bootstrap.py +0 -15
  1408. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/__init__.py +0 -0
  1409. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/synthetic_session.py +0 -424
  1410. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_bootstrap_and_mode.py +0 -115
  1411. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct.py +0 -220
  1412. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct_integration.py +0 -158
  1413. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_helpers.py +0 -287
  1414. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_integration.py +0 -247
  1415. package/skills/investigating-agentforce-d360/scripts/tests/test_dc_and_resolve_session.py +0 -433
  1416. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions.py +0 -458
  1417. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions_grep_ci.py +0 -193
  1418. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_helpers.py +0 -266
  1419. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_identity.py +0 -528
  1420. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_main.py +0 -251
  1421. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall.py +0 -229
  1422. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall_full.py +0 -283
  1423. package/skills/investigating-agentforce-d360/scripts/tests/test_identity_coherence.py +0 -327
  1424. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_branches.py +0 -256
  1425. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_gateway_direct.py +0 -130
  1426. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_helpers.py +0 -291
  1427. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_integration.py +0 -220
  1428. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_planner_llm_calls.py +0 -284
  1429. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_show_prompts_gating.py +0 -215
  1430. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_from_disk.py +0 -100
  1431. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_session_main.py +0 -149
  1432. package/skills/investigating-agentforce-d360/scripts/tests/test_runtime_override.py +0 -104
  1433. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape.py +0 -95
  1434. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape_dropped_by_stdm.py +0 -85
  1435. package/skills/managing-cdc-enablement/SKILL.md +0 -164
  1436. package/skills/managing-cdc-enablement/assets/PlatformEventChannel-template.xml +0 -5
  1437. package/skills/managing-cdc-enablement/assets/PlatformEventChannelMember-template.xml +0 -11
  1438. package/skills/managing-cdc-enablement/references/deploy-troubleshooting.md +0 -73
  1439. package/skills/managing-cdc-enablement/references/filter-expressions.md +0 -93
  1440. package/skills/managing-managed-event-subscription/SKILL.md +0 -152
  1441. package/skills/managing-managed-event-subscription/assets/managed-event-subscription-template.xml +0 -20
  1442. package/skills/managing-managed-event-subscription/references/delete-guide.md +0 -57
  1443. package/skills/managing-managed-event-subscription/references/topic-name-formats.md +0 -26
  1444. package/skills/managing-managed-event-subscription/references/update-constraints.md +0 -30
  1445. package/skills/modeling-omnistudio-epc-catalog/CREDITS.md +0 -14
  1446. package/skills/modeling-omnistudio-epc-catalog/README.md +0 -89
  1447. package/skills/modeling-omnistudio-epc-catalog/SKILL.md +0 -394
  1448. package/skills/modeling-omnistudio-epc-catalog/assets/attribute-assignment-template.json +0 -402
  1449. package/skills/modeling-omnistudio-epc-catalog/assets/compiled-attribute-overrides-template.json +0 -43
  1450. package/skills/modeling-omnistudio-epc-catalog/assets/completion-block-template.txt +0 -8
  1451. package/skills/modeling-omnistudio-epc-catalog/assets/decomposition-relationships-template.json +0 -233
  1452. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_AttributeAssignments.json +0 -514
  1453. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_CompiledAttributeOverrides.json +0 -21
  1454. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DataPack.json +0 -649
  1455. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DecompositionRelationships.json +0 -200
  1456. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ObjectFieldAttributes.json +0 -138
  1457. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OrchestrationScenarios.json +0 -54
  1458. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OverrideDefinitions.json +0 -266
  1459. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ParentKeys.json +0 -23
  1460. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PriceListEntries.json +0 -54
  1461. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PricebookEntries.json +0 -35
  1462. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ProductChildItems.json +0 -34
  1463. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_RuleAssignments.json +0 -21
  1464. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_AttributeAssignments.json +0 -410
  1465. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DataPack.json +0 -535
  1466. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DecompositionRelationships.json +0 -35
  1467. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ObjectFieldAttributes.json +0 -138
  1468. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_OrchestrationScenarios.json +0 -28
  1469. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ParentKeys.json +0 -23
  1470. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PriceListEntries.json +0 -220
  1471. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PricebookEntries.json +0 -35
  1472. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ProductChildItems.json +0 -414
  1473. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_AttributeAssignments.json +0 -382
  1474. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DataPack.json +0 -565
  1475. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DecompositionRelationships.json +0 -35
  1476. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ObjectFieldAttributes.json +0 -104
  1477. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_OrchestrationScenarios.json +0 -28
  1478. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ParentKeys.json +0 -13
  1479. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PriceListEntries.json +0 -106
  1480. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PricebookEntries.json +0 -35
  1481. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ProductChildItems.json +0 -72
  1482. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_AttributeAssignments.json +0 -142
  1483. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DataPack.json +0 -377
  1484. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DecompositionRelationships.json +0 -35
  1485. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ObjectFieldAttributes.json +0 -36
  1486. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ParentKeys.json +0 -8
  1487. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PriceListEntries.json +0 -54
  1488. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PricebookEntries.json +0 -35
  1489. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ProductChildItems.json +0 -34
  1490. package/skills/modeling-omnistudio-epc-catalog/assets/object-field-attributes-template.json +0 -138
  1491. package/skills/modeling-omnistudio-epc-catalog/assets/orchestration-scenarios-template.json +0 -54
  1492. package/skills/modeling-omnistudio-epc-catalog/assets/override-definitions-template.json +0 -134
  1493. package/skills/modeling-omnistudio-epc-catalog/assets/parent-keys-template.json +0 -29
  1494. package/skills/modeling-omnistudio-epc-catalog/assets/price-list-entries-template.json +0 -158
  1495. package/skills/modeling-omnistudio-epc-catalog/assets/pricebook-entries-template.json +0 -35
  1496. package/skills/modeling-omnistudio-epc-catalog/assets/product-child-item-template.json +0 -338
  1497. package/skills/modeling-omnistudio-epc-catalog/assets/product2-offer-template.json +0 -527
  1498. package/skills/modeling-omnistudio-epc-catalog/examples/.gitkeep +0 -1
  1499. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_AttributeAssignments.json +0 -95
  1500. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_CompiledAttributeOverrides.json +0 -1
  1501. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DataPack.json +0 -214
  1502. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DecompositionRelationships.json +0 -28
  1503. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ObjectFieldAttributes.json +0 -98
  1504. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OrchestrationScenarios.json +0 -22
  1505. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OverrideDefinitions.json +0 -1
  1506. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ParentKeys.json +0 -13
  1507. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PriceListEntries.json +0 -35
  1508. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PricebookEntries.json +0 -28
  1509. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ProductChildItems.json +0 -110
  1510. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/TRANSCRIPT.md +0 -58
  1511. package/skills/modeling-omnistudio-epc-catalog/references/epc-field-guide.md +0 -90
  1512. package/skills/modeling-omnistudio-epc-catalog/references/naming-conventions.md +0 -80
  1513. package/skills/modeling-omnistudio-epc-catalog/references/scoring-model.md +0 -57
  1514. package/skills/modeling-omnistudio-epc-catalog/scripts/cli-validation-commands.sh +0 -19
  1515. package/skills/modeling-omnistudio-epc-catalog/scripts/sample-invocations.sh +0 -18
  1516. package/skills/observing-agentforce/SKILL.md +0 -366
  1517. package/skills/observing-agentforce/apex/AgentforceOptimizeService.cls +0 -1262
  1518. package/skills/observing-agentforce/apex/AgentforceOptimizeService.cls-meta.xml +0 -5
  1519. package/skills/observing-agentforce/references/improve-reference.md +0 -359
  1520. package/skills/observing-agentforce/references/issue-classification.md +0 -220
  1521. package/skills/observing-agentforce/references/reproduce-reference.md +0 -131
  1522. package/skills/observing-agentforce/references/stdm-queries.md +0 -373
  1523. package/skills/observing-agentforce/references/stdm-schema.md +0 -189
  1524. package/skills/orchestrating-datacloud/CREDITS.md +0 -15
  1525. package/skills/orchestrating-datacloud/README.md +0 -127
  1526. package/skills/orchestrating-datacloud/SKILL.md +0 -235
  1527. package/skills/orchestrating-datacloud/UPSTREAM.md +0 -45
  1528. package/skills/orchestrating-datacloud/assets/definitions/activation-target.template.json +0 -5
  1529. package/skills/orchestrating-datacloud/assets/definitions/activation.template.json +0 -7
  1530. package/skills/orchestrating-datacloud/assets/definitions/calculated-insight.template.json +0 -7
  1531. package/skills/orchestrating-datacloud/assets/definitions/data-action-target.template.json +0 -5
  1532. package/skills/orchestrating-datacloud/assets/definitions/data-action.template.json +0 -5
  1533. package/skills/orchestrating-datacloud/assets/definitions/data-graph.template.json +0 -21
  1534. package/skills/orchestrating-datacloud/assets/definitions/data-stream.template.json +0 -55
  1535. package/skills/orchestrating-datacloud/assets/definitions/dmo.template.json +0 -17
  1536. package/skills/orchestrating-datacloud/assets/definitions/identity-resolution.template.json +0 -30
  1537. package/skills/orchestrating-datacloud/assets/definitions/mapping.template.json +0 -14
  1538. package/skills/orchestrating-datacloud/assets/definitions/relationship.template.json +0 -12
  1539. package/skills/orchestrating-datacloud/assets/definitions/search-index.template.json +0 -9
  1540. package/skills/orchestrating-datacloud/assets/definitions/segment.template.json +0 -16
  1541. package/skills/orchestrating-datacloud/references/feature-readiness.md +0 -157
  1542. package/skills/orchestrating-datacloud/references/plugin-setup.md +0 -138
  1543. package/skills/orchestrating-datacloud/scripts/bootstrap-plugin.sh +0 -53
  1544. package/skills/orchestrating-datacloud/scripts/diagnose-org.mjs +0 -511
  1545. package/skills/orchestrating-datacloud/scripts/generate-manifest.mjs +0 -68
  1546. package/skills/orchestrating-datacloud/scripts/verify-plugin.sh +0 -58
  1547. package/skills/platform-agentexchange-partner-offers-enable/SKILL.md +0 -111
  1548. package/skills/platform-agentexchange-partner-offers-enable/assets/org-pref-template.md +0 -27
  1549. package/skills/platform-agentexchange-partner-offers-enable/examples/org-preference-settings.xml +0 -4
  1550. package/skills/preparing-datacloud/CREDITS.md +0 -7
  1551. package/skills/preparing-datacloud/README.md +0 -51
  1552. package/skills/preparing-datacloud/SKILL.md +0 -190
  1553. package/skills/preparing-datacloud/examples/ingestion-api/.env.example +0 -8
  1554. package/skills/preparing-datacloud/examples/ingestion-api/README.md +0 -48
  1555. package/skills/preparing-datacloud/examples/ingestion-api/send-data.py +0 -144
  1556. package/skills/querying-soql/CREDITS.md +0 -21
  1557. package/skills/querying-soql/README.md +0 -41
  1558. package/skills/querying-soql/SKILL.md +0 -142
  1559. package/skills/querying-soql/assets/aggregate-queries.soql +0 -242
  1560. package/skills/querying-soql/assets/basic-queries.soql +0 -188
  1561. package/skills/querying-soql/assets/bulkified-query-pattern.cls +0 -280
  1562. package/skills/querying-soql/assets/optimization-patterns.soql +0 -259
  1563. package/skills/querying-soql/assets/relationship-queries.soql +0 -203
  1564. package/skills/querying-soql/assets/selector-class.cls +0 -219
  1565. package/skills/querying-soql/references/anti-patterns.md +0 -348
  1566. package/skills/querying-soql/references/cli-commands.md +0 -358
  1567. package/skills/querying-soql/references/field-coverage-rules.md +0 -514
  1568. package/skills/querying-soql/references/query-optimization.md +0 -142
  1569. package/skills/querying-soql/references/selector-patterns.md +0 -479
  1570. package/skills/querying-soql/references/soql-reference.md +0 -227
  1571. package/skills/querying-soql/references/soql-syntax-reference.md +0 -208
  1572. package/skills/querying-soql/scripts/post-tool-validate.py +0 -322
  1573. package/skills/retrieving-datacloud/CREDITS.md +0 -7
  1574. package/skills/retrieving-datacloud/README.md +0 -44
  1575. package/skills/retrieving-datacloud/SKILL.md +0 -119
  1576. package/skills/retrieving-datacloud/examples/search-indexes/hybrid-structured.json +0 -44
  1577. package/skills/retrieving-datacloud/examples/search-indexes/vector-knowledge.json +0 -43
  1578. package/skills/reviewing-lwc-mobile-offline/SKILL.md +0 -167
  1579. package/skills/reviewing-lwc-mobile-offline/references/grounding.md +0 -7
  1580. package/skills/reviewing-lwc-mobile-offline/references/inline-graphql.md +0 -43
  1581. package/skills/reviewing-lwc-mobile-offline/references/komaci-eslint.md +0 -125
  1582. package/skills/reviewing-lwc-mobile-offline/references/lwc-if.md +0 -78
  1583. package/skills/reviewing-lwc-mobile-offline/scripts/komaci.config.mjs +0 -18
  1584. package/skills/reviewing-lwc-mobile-offline/scripts/package.json +0 -10
  1585. package/skills/reviewing-lwc-mobile-offline/scripts/run-komaci.sh +0 -69
  1586. package/skills/running-apex-tests/CREDITS.md +0 -22
  1587. package/skills/running-apex-tests/README.md +0 -94
  1588. package/skills/running-apex-tests/SKILL.md +0 -157
  1589. package/skills/running-apex-tests/assets/basic-test.cls +0 -169
  1590. package/skills/running-apex-tests/assets/bulk-test.cls +0 -255
  1591. package/skills/running-apex-tests/assets/dml-mock.cls +0 -339
  1592. package/skills/running-apex-tests/assets/mock-callout-test.cls +0 -353
  1593. package/skills/running-apex-tests/assets/stub-provider-example.cls +0 -364
  1594. package/skills/running-apex-tests/assets/test-data-factory.cls +0 -328
  1595. package/skills/running-apex-tests/hooks/scripts/parse-test-results.py +0 -364
  1596. package/skills/running-apex-tests/references/cli-commands.md +0 -289
  1597. package/skills/running-apex-tests/references/mocking-patterns.md +0 -500
  1598. package/skills/running-apex-tests/references/performance-optimization.md +0 -283
  1599. package/skills/running-apex-tests/references/test-fix-loop.md +0 -49
  1600. package/skills/running-apex-tests/references/test-patterns.md +0 -154
  1601. package/skills/running-apex-tests/references/testing-best-practices.md +0 -509
  1602. package/skills/running-code-analyzer/SKILL.md +0 -495
  1603. package/skills/running-code-analyzer/examples/README.md +0 -38
  1604. package/skills/running-code-analyzer/examples/basic-scan-output.json +0 -92
  1605. package/skills/running-code-analyzer/examples/command-variations.md +0 -333
  1606. package/skills/running-code-analyzer/examples/fix-application-before-after.md +0 -142
  1607. package/skills/running-code-analyzer/examples/large-scan-output.json +0 -67
  1608. package/skills/running-code-analyzer/examples/security-focused-output.json +0 -95
  1609. package/skills/running-code-analyzer/references/command-examples.md +0 -27
  1610. package/skills/running-code-analyzer/references/engine-reference.md +0 -34
  1611. package/skills/running-code-analyzer/references/error-handling.md +0 -29
  1612. package/skills/running-code-analyzer/references/flag-reference.md +0 -96
  1613. package/skills/running-code-analyzer/references/post-scan-workflows.md +0 -286
  1614. package/skills/running-code-analyzer/references/quick-start.md +0 -28
  1615. package/skills/running-code-analyzer/references/special-behaviors.md +0 -83
  1616. package/skills/running-code-analyzer/references/vendor-file-handling.md +0 -239
  1617. package/skills/running-code-analyzer/scripts/apply-fixes.js +0 -86
  1618. package/skills/running-code-analyzer/scripts/describe-rule.js +0 -382
  1619. package/skills/running-code-analyzer/scripts/discover-fixes.js +0 -34
  1620. package/skills/running-code-analyzer/scripts/filter-violations.js +0 -405
  1621. package/skills/running-code-analyzer/scripts/list-rules.js +0 -260
  1622. package/skills/running-code-analyzer/scripts/parse-results.js +0 -59
  1623. package/skills/running-code-analyzer/scripts/query-results.js +0 -230
  1624. package/skills/running-code-analyzer/scripts/summarize-fixes.js +0 -32
  1625. package/skills/running-code-analyzer/scripts/verify-execution.sh +0 -28
  1626. package/skills/searching-media/SKILL.md +0 -348
  1627. package/skills/segmenting-datacloud/CREDITS.md +0 -3
  1628. package/skills/segmenting-datacloud/README.md +0 -36
  1629. package/skills/segmenting-datacloud/SKILL.md +0 -114
  1630. package/skills/switching-org/SKILL.md +0 -28
  1631. package/skills/testing-agentforce/SKILL.md +0 -333
  1632. package/skills/testing-agentforce/assets/basic-test-spec.yaml +0 -63
  1633. package/skills/testing-agentforce/assets/guardrail-test-spec.yaml +0 -105
  1634. package/skills/testing-agentforce/assets/standard-test-spec.yaml +0 -127
  1635. package/skills/testing-agentforce/references/action-execution.md +0 -241
  1636. package/skills/testing-agentforce/references/batch-testing.md +0 -274
  1637. package/skills/testing-agentforce/references/preview-testing.md +0 -353
  1638. package/skills/testing-agentforce/references/test-report-format.md +0 -160
  1639. package/skills/testing-agentforce/references/troubleshooting.md +0 -73
  1640. package/skills/uplifting-components-to-slds2/SKILL.md +0 -239
  1641. package/skills/uplifting-components-to-slds2/references/color-hooks-decision-guide.md +0 -459
  1642. package/skills/uplifting-components-to-slds2/references/common-patterns.md +0 -87
  1643. package/skills/uplifting-components-to-slds2/references/examples.md +0 -461
  1644. package/skills/uplifting-components-to-slds2/references/migration-checklist.md +0 -67
  1645. package/skills/uplifting-components-to-slds2/references/non-color-hooks-decision-guide.md +0 -333
  1646. package/skills/uplifting-components-to-slds2/references/rule-lwc-token-to-slds-hook.md +0 -135
  1647. package/skills/uplifting-components-to-slds2/references/rule-no-deprecated-tokens-slds1.md +0 -211
  1648. package/skills/uplifting-components-to-slds2/references/rule-no-hardcoded-values.md +0 -160
  1649. package/skills/uplifting-components-to-slds2/references/rule-no-slds-class-overrides.md +0 -126
  1650. package/skills/using-mobile-native-capabilities/SKILL.md +0 -181
  1651. package/skills/using-mobile-native-capabilities/references/app-review.md +0 -68
  1652. package/skills/using-mobile-native-capabilities/references/ar-space-capture.md +0 -125
  1653. package/skills/using-mobile-native-capabilities/references/barcode-scanner.md +0 -219
  1654. package/skills/using-mobile-native-capabilities/references/base-capability.md +0 -22
  1655. package/skills/using-mobile-native-capabilities/references/biometrics.md +0 -90
  1656. package/skills/using-mobile-native-capabilities/references/calendar.md +0 -213
  1657. package/skills/using-mobile-native-capabilities/references/contacts.md +0 -232
  1658. package/skills/using-mobile-native-capabilities/references/document-scanner.md +0 -342
  1659. package/skills/using-mobile-native-capabilities/references/geofencing.md +0 -123
  1660. package/skills/using-mobile-native-capabilities/references/location.md +0 -158
  1661. package/skills/using-mobile-native-capabilities/references/mobile-capabilities.md +0 -30
  1662. package/skills/using-mobile-native-capabilities/references/nfc.md +0 -181
  1663. package/skills/using-mobile-native-capabilities/references/payments.md +0 -95
  1664. package/skills/using-salesforce-archive/SKILL.md +0 -121
  1665. package/skills/using-salesforce-archive/examples/monitor-failed-jobs.md +0 -47
  1666. package/skills/using-salesforce-archive/references/archive-activity-entity.md +0 -59
  1667. package/skills/using-salesforce-archive/references/connect-api-operations.md +0 -157
  1668. package/skills/using-ui-bundle-salesforce-data/SKILL.md +0 -638
  1669. package/skills/using-ui-bundle-salesforce-data/scripts/graphql-search.sh +0 -191
  1670. package/skills/validating-slds/SKILL.md +0 -262
  1671. package/skills/validating-slds/references/quality-checks.md +0 -308
  1672. package/skills/validating-slds/references/report-format.md +0 -302
  1673. package/skills/validating-slds/scripts/analyze-quality.cjs +0 -521
  1674. /package/skills/{getting-datacloud-schema → data360-schema-get}/scripts/get_dlo_schema.py +0 -0
  1675. /package/skills/{getting-datacloud-schema → data360-schema-get}/scripts/get_dmo_schema.py +0 -0
@@ -1,3359 +0,0 @@
1
- """Phase 2 Batch 1 integration tests for `main.py`.
2
-
3
- End-to-end pipeline exercise without hitting a real org. Every SOQL-level
4
- primitive (`fetch_*`, `run_sf`, `probe_channels`) is mocked on the
5
- `main` module's import namespace so the orchestrator sees synthetic
6
- rows shaped like live describe output.
7
-
8
- What these tests assert:
9
- * RESULT-level behavior — the `.emit_ctx.json` that main.py writes
10
- is the contract with emit_result.py. We read that JSON back and
11
- assert status + key counts.
12
- * Tree shape — `declared_action_tree.json` is parsed; node count,
13
- depth, kind counts, and the AGENT block are checked against
14
- fixture expectations.
15
- * Failure-mode mapping — probe failures map to RETRIEVE_FAILED
16
- (design decision, see module docstring); empty planner fetch →
17
- AGENT_NOT_FOUND; empty bot fetch → AGENT_NOT_FOUND + AVAILABLE_BOTS.
18
-
19
- Every test must run offline. If you see a real `sf` subprocess spawn or
20
- a real `urllib` request in a failure output, a mock is missing.
21
- """
22
- from __future__ import annotations
23
-
24
- import json
25
- import os
26
- import subprocess
27
- import tempfile
28
- import unittest
29
- from pathlib import Path
30
- from unittest import mock
31
-
32
- from . import _bootstrap # noqa: F401
33
-
34
- import config # type: ignore
35
- import soql_loader # type: ignore
36
- import main # type: ignore
37
- from tests.fixtures import genai_payloads as fx # type: ignore
38
-
39
- # SKILL_ROOT is now file-relative (Path(__file__).resolve().parent.parent in
40
- # config.py), so config.SOQL_DIR auto-resolves to the repo's assets/soql/
41
- # under test. No env-var setup is needed.
42
- # soql_loader still captures SOQL_DIR via `from config import SOQL_DIR` at
43
- # module top, so we mirror its binding here defensively in case any test
44
- # imported soql_loader before config's file-relative resolution kicked in.
45
- _REPO_SOQL_DIR = Path(__file__).resolve().parent.parent.parent / "assets" / "soql"
46
- soql_loader.SOQL_DIR = _REPO_SOQL_DIR
47
-
48
-
49
- def _args(work_dir: Path, **overrides) -> list[str]:
50
- base = [
51
- "--org-alias", "test-org",
52
- "--agent", overrides.pop("agent", "MyAgent"),
53
- "--work-dir", str(work_dir),
54
- "--parallelism", "2",
55
- ]
56
- for k, v in overrides.items():
57
- flag = "--" + k.replace("_", "-")
58
- if isinstance(v, bool):
59
- if v:
60
- base.append(flag)
61
- else:
62
- base.extend([flag, str(v)])
63
- return base
64
-
65
-
66
- def _mock_wave_a_classic():
67
- """Patch every main.fetch_* Wave A function with classic-shape returns."""
68
- return [
69
- mock.patch.object(main, "fetch_planner_definition", return_value=fx.CLASSIC_PLANNER),
70
- mock.patch.object(main, "fetch_plugins_by_planner", return_value=fx.CLASSIC_PLUGINS),
71
- mock.patch.object(main, "fetch_planner_bundle_functions", return_value=fx.CLASSIC_BUNDLE_FN_JOIN),
72
- mock.patch.object(main, "fetch_functions_by_plugins", return_value=fx.CLASSIC_FUNCTIONS),
73
- mock.patch.object(main, "fetch_plugin_instructions", return_value=fx.CLASSIC_INSTRUCTIONS),
74
- mock.patch.object(main, "fetch_plugin_functions", return_value=fx.CLASSIC_PLUGIN_FUNCTIONS),
75
- mock.patch.object(main, "fetch_planner_attrs", return_value=fx.CLASSIC_ATTRS),
76
- ]
77
-
78
-
79
- def _mock_wave_b_classic():
80
- return [
81
- mock.patch.object(main, "fetch_apex_bodies_by_names", return_value=fx.CLASSIC_APEX_ROWS),
82
- mock.patch.object(main, "fetch_apex_bodies_by_ids", return_value=[]),
83
- mock.patch.object(main, "fetch_flow_definition_ids_by_names", return_value=fx.CLASSIC_FLOW_DEFS),
84
- mock.patch.object(main, "fetch_flow_definition_by_ids", return_value=[]),
85
- mock.patch.object(
86
- main, "fetch_flow_metadata",
87
- side_effect=lambda vid, *a, **kw: fx.CLASSIC_FLOW_METADATA.get(vid),
88
- ),
89
- ]
90
-
91
-
92
- def _mock_wave_a_nga():
93
- return [
94
- mock.patch.object(main, "fetch_planner_definition", return_value=fx.NGA_PLANNER),
95
- mock.patch.object(main, "fetch_plugins_by_planner", return_value=fx.NGA_PLUGINS),
96
- mock.patch.object(main, "fetch_planner_bundle_functions", return_value=[]),
97
- mock.patch.object(main, "fetch_functions_by_plugins", return_value=fx.NGA_FUNCTIONS),
98
- mock.patch.object(main, "fetch_plugin_instructions", return_value=[]),
99
- mock.patch.object(main, "fetch_plugin_functions", return_value=fx.NGA_PLUGIN_FUNCTIONS),
100
- mock.patch.object(main, "fetch_planner_attrs", return_value=[]),
101
- ]
102
-
103
-
104
- def _mock_wave_b_nga():
105
- return [
106
- mock.patch.object(main, "fetch_apex_bodies_by_names", return_value=[]),
107
- mock.patch.object(main, "fetch_apex_bodies_by_ids", return_value=fx.NGA_APEX_BY_ID),
108
- mock.patch.object(main, "fetch_flow_definition_ids_by_names", return_value=[]),
109
- mock.patch.object(main, "fetch_flow_definition_by_ids", return_value=fx.NGA_FLOW_DEF_BY_ID),
110
- mock.patch.object(main, "fetch_flow_metadata", return_value={
111
- "Id": "301VF999NGAVER", "FullName": "NGAResolvedFlow-1", "Metadata": {},
112
- }),
113
- ]
114
-
115
-
116
- def _mock_auth_probe(probe_result=None):
117
- """Patch run_sf (for org_display) + probe_channels + bot data fetches."""
118
- probe_result = probe_result or fx.probe_ok_payload()
119
- org_display_payload = {
120
- "status": 0,
121
- "result": {
122
- "instanceUrl": "https://example.my.salesforce.com",
123
- "accessToken": "00Dxx0000000000!AQ_fake_token_value",
124
- "id": "https://login.salesforce.com/id/00Dxx0000000000AAA/005xx0000000000AAA",
125
- "apiVersion": "60.0",
126
- },
127
- }
128
- # The code reads `result.id` — some orgs return a full URL here, some
129
- # return the 18-char id directly. We patch to a direct 18-char id to
130
- # keep the derivation trivial.
131
- org_display_payload["result"]["id"] = "00Dxx0000000000AAA"
132
- return [
133
- mock.patch.object(main, "run_sf", return_value=org_display_payload),
134
- mock.patch.object(main, "probe_channels", return_value=probe_result),
135
- ]
136
-
137
-
138
- def _mock_bot_resolution(agent_api_name="MyAgent", versions=("v5",), active="v5",
139
- bot_def=None):
140
- bot_def = bot_def or fx.BOT_DEFINITION_DETAIL_CLASSIC
141
- return [
142
- mock.patch.object(
143
- main, "fetch_bot_versions",
144
- return_value=fx.make_bot_versions(agent_api_name, versions, active),
145
- ),
146
- mock.patch.object(main, "fetch_bot_definition_details", return_value=bot_def),
147
- ]
148
-
149
-
150
- def _apply_all(patches):
151
- """Enter every patch in `patches`; return a list of the started mocks."""
152
- mocks = []
153
- for p in patches:
154
- mocks.append(p.start())
155
- return mocks
156
-
157
-
158
- def _read_ctx(work_dir: Path) -> dict:
159
- return json.loads((work_dir / ".emit_ctx.json").read_text())
160
-
161
-
162
- def _read_tree(work_dir: Path) -> dict:
163
- return json.loads((work_dir / "declared_action_tree.json").read_text())
164
-
165
-
166
- # ---------------------------------------------------------------------------
167
- # Classic happy path
168
- # ---------------------------------------------------------------------------
169
-
170
-
171
- class ClassicHappyPathTests(unittest.TestCase):
172
- def test_classic_pipeline_builds_tree(self):
173
- with tempfile.TemporaryDirectory() as tmp:
174
- work_dir = Path(tmp) / "work"
175
- data_root = Path(tmp) / "data"
176
- cache_root = Path(tmp) / "cache"
177
-
178
- patches = [
179
- *_mock_auth_probe(),
180
- *_mock_bot_resolution(),
181
- *_mock_wave_a_classic(),
182
- *_mock_wave_b_classic(),
183
- # Keep pipeline writes contained to tmp.
184
- mock.patch.object(main, "build_agent_data_dir",
185
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
186
- mock.patch.object(main, "build_agent_cache_dir",
187
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
188
- ]
189
- _apply_all(patches)
190
- try:
191
- rc = main.main(_args(work_dir))
192
- finally:
193
- for p in patches:
194
- p.stop()
195
-
196
- self.assertEqual(rc, 0)
197
- ctx = _read_ctx(work_dir)
198
- self.assertIn(ctx["status"], ("OK", "PARTIAL_OK"))
199
- self.assertEqual(ctx["agent_api_name"], "MyAgent")
200
- self.assertEqual(ctx["agent_version"], "v5")
201
- self.assertTrue(ctx["version_auto_picked"])
202
-
203
- tree = _read_tree(work_dir)
204
- # 6 topics, no bundle-direct actions (a planner never has direct
205
- # functions — 2026-05-05). Root has exactly TOPIC children.
206
- self.assertEqual(len(tree["root"]["children"]), 6)
207
- # Agent block fields resolved from BotDefinition detail row
208
- self.assertEqual(tree["agent"]["generation"], "classic")
209
- self.assertEqual(tree["agent"]["planner_type"],
210
- "AiCopilot__ReActAiPlannerV1")
211
- # Kind counts — BOT_DEFINITION, TOPIC(6), GEN_AI_FUNCTION(2 in
212
- # Topic1, 0 elsewhere).
213
- counts = tree["_kind_counts"]
214
- self.assertEqual(counts.get("BOT_DEFINITION"), 1)
215
- self.assertEqual(counts.get("TOPIC"), 6)
216
- self.assertEqual(counts.get("GEN_AI_FUNCTION"), 2)
217
-
218
-
219
- # ---------------------------------------------------------------------------
220
- # NGA happy path
221
- # ---------------------------------------------------------------------------
222
-
223
-
224
- class NgaHappyPathTests(unittest.TestCase):
225
- def test_nga_pipeline_reverse_lookup_builds_tree(self):
226
- with tempfile.TemporaryDirectory() as tmp:
227
- work_dir = Path(tmp) / "work"
228
- data_root = Path(tmp) / "data"
229
- cache_root = Path(tmp) / "cache"
230
-
231
- patches = [
232
- *_mock_auth_probe(),
233
- *_mock_bot_resolution(
234
- agent_api_name="MyAgent2",
235
- bot_def=fx.BOT_DEFINITION_DETAIL_NGA,
236
- ),
237
- *_mock_wave_a_nga(),
238
- *_mock_wave_b_nga(),
239
- mock.patch.object(main, "build_agent_data_dir",
240
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
241
- mock.patch.object(main, "build_agent_cache_dir",
242
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
243
- ]
244
- _apply_all(patches)
245
- try:
246
- rc = main.main(_args(work_dir, agent="MyAgent2"))
247
- finally:
248
- for p in patches:
249
- p.stop()
250
-
251
- self.assertEqual(rc, 0)
252
- tree = _read_tree(work_dir)
253
- self.assertEqual(tree["agent"]["generation"], "nga")
254
- self.assertEqual(tree["agent"]["planner_type"],
255
- "Atlas__ConcurrentMultiAgentOrchestration")
256
- # 1 topic + 0 bundle actions; topic has 2 functions. Confirm
257
- # both topic-scope functions are present.
258
- self.assertEqual(tree["_kind_counts"].get("TOPIC"), 1)
259
- self.assertEqual(tree["_kind_counts"].get("GEN_AI_FUNCTION"), 2)
260
-
261
-
262
- # ---------------------------------------------------------------------------
263
- # Sequential planner (no plugins)
264
- # ---------------------------------------------------------------------------
265
-
266
-
267
- class SequentialPlannerTests(unittest.TestCase):
268
- def test_zero_plugins_one_bundle_function(self):
269
- with tempfile.TemporaryDirectory() as tmp:
270
- work_dir = Path(tmp) / "work"
271
- data_root = Path(tmp) / "data"
272
- cache_root = Path(tmp) / "cache"
273
-
274
- patches = [
275
- *_mock_auth_probe(),
276
- *_mock_bot_resolution(agent_api_name="SequentialAgent"),
277
- mock.patch.object(main, "fetch_planner_definition",
278
- return_value=fx.SEQ_PLANNER),
279
- mock.patch.object(main, "fetch_plugins_by_planner", return_value=[]),
280
- mock.patch.object(main, "fetch_planner_bundle_functions", return_value=[]),
281
- mock.patch.object(main, "fetch_functions_by_plugins",
282
- return_value=fx.SEQ_FUNCTIONS),
283
- mock.patch.object(main, "fetch_plugin_instructions", return_value=[]),
284
- mock.patch.object(main, "fetch_plugin_functions", return_value=[]),
285
- mock.patch.object(main, "fetch_planner_attrs", return_value=[]),
286
- mock.patch.object(main, "fetch_apex_bodies_by_names", return_value=[]),
287
- mock.patch.object(main, "fetch_apex_bodies_by_ids", return_value=[]),
288
- mock.patch.object(main, "fetch_flow_definition_ids_by_names", return_value=[]),
289
- mock.patch.object(main, "fetch_flow_definition_by_ids", return_value=[]),
290
- mock.patch.object(main, "fetch_flow_metadata", return_value=None),
291
- mock.patch.object(main, "build_agent_data_dir",
292
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
293
- mock.patch.object(main, "build_agent_cache_dir",
294
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
295
- ]
296
- _apply_all(patches)
297
- try:
298
- rc = main.main(_args(work_dir, agent="SequentialAgent"))
299
- finally:
300
- for p in patches:
301
- p.stop()
302
-
303
- self.assertEqual(rc, 0)
304
- tree = _read_tree(work_dir)
305
- # 2026-05-05: a planner never has direct functions. A
306
- # SequentialPlannerIntentClassifier bot with zero plugins
307
- # therefore has zero declared actions — `functions_by_plugins`
308
- # short-circuits on empty plugin_ids. The tree is a bare
309
- # BOT_DEFINITION with no children; no TOPIC, no
310
- # GEN_AI_FUNCTION, no STANDARD_ACTION.
311
- counts = tree["_kind_counts"]
312
- self.assertNotIn("TOPIC", counts)
313
- self.assertNotIn("GEN_AI_FUNCTION", counts)
314
- self.assertNotIn("STANDARD_ACTION", counts)
315
- self.assertEqual(counts.get("BOT_DEFINITION"), 1)
316
-
317
-
318
- # ---------------------------------------------------------------------------
319
- # Bot not found
320
- # ---------------------------------------------------------------------------
321
-
322
-
323
- class BotNotFoundTests(unittest.TestCase):
324
- def test_empty_bot_versions_emits_agent_not_found(self):
325
- with tempfile.TemporaryDirectory() as tmp:
326
- work_dir = Path(tmp) / "work"
327
-
328
- patches = [
329
- *_mock_auth_probe(),
330
- mock.patch.object(main, "fetch_bot_versions", return_value=[]),
331
- ]
332
- _apply_all(patches)
333
- try:
334
- rc = main.main(_args(work_dir, agent="MissingAgent"))
335
- finally:
336
- for p in patches:
337
- p.stop()
338
-
339
- self.assertEqual(rc, 1)
340
- ctx = _read_ctx(work_dir)
341
- self.assertEqual(ctx["status"], "AGENT_NOT_FOUND")
342
- self.assertEqual(ctx["available_bots"], "")
343
-
344
-
345
- # ---------------------------------------------------------------------------
346
- # Probe failure on mandatory field → RETRIEVE_FAILED + "schema-drift" detail.
347
- # ---------------------------------------------------------------------------
348
-
349
-
350
- class ProbeFailureTests(unittest.TestCase):
351
- def test_probe_failed_emits_retrieve_failed_schema_drift(self):
352
- with tempfile.TemporaryDirectory() as tmp:
353
- work_dir = Path(tmp) / "work"
354
-
355
- patches = _mock_auth_probe(
356
- probe_result=fx.probe_failed_payload(
357
- sobject="GenAiPlannerDefinition",
358
- missing=["PlannerType"],
359
- ),
360
- )
361
- _apply_all(patches)
362
- try:
363
- rc = main.main(_args(work_dir))
364
- finally:
365
- for p in patches:
366
- p.stop()
367
-
368
- self.assertEqual(rc, 1)
369
- ctx = _read_ctx(work_dir)
370
- self.assertEqual(ctx["status"], "RETRIEVE_FAILED")
371
- self.assertIn("schema-drift", ctx["error_detail"])
372
- self.assertIn("PlannerType", ctx["error_detail"])
373
-
374
-
375
- # ---------------------------------------------------------------------------
376
- # Cache hit / force refresh
377
- # ---------------------------------------------------------------------------
378
-
379
-
380
- class CacheBehaviourTests(unittest.TestCase):
381
- def test_cache_hit_skips_wave_calls(self):
382
- """Populate a fresh manifest, confirm pipeline returns CACHE_HIT=true
383
- without invoking any Wave A fetcher."""
384
- with tempfile.TemporaryDirectory() as tmp:
385
- work_dir = Path(tmp) / "work"
386
- data_root = Path(tmp) / "data"
387
- cache_root = Path(tmp) / "cache"
388
- data_dir = data_root / "00Dxx0000000000" / "MyAgent__v5"
389
- cache_dir = cache_root / "00Dxx0000000000" / "MyAgent__v5"
390
- cache_dir.mkdir(parents=True)
391
- data_dir.mkdir(parents=True)
392
- tree_base = "MyAgent_v5_metadata_tree"
393
- (data_dir / f"{tree_base}.json").write_text("{}")
394
-
395
- import datetime as dt
396
- from config import SCHEMA_VERSION
397
- manifest = {
398
- "built_at_utc": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z"),
399
- "schema_version": SCHEMA_VERSION,
400
- "agent": {
401
- "version": "v5", "bot_id": "0Xa000000000ABC",
402
- "generation": "classic", "_version_auto_picked": True,
403
- },
404
- "node_count": 12, "depth": 3, "kind_counts": {},
405
- "ttl_days": 7,
406
- "data_path": str(data_dir / f"{tree_base}.json"),
407
- "partial": False, "unresolved_count": 0,
408
- }
409
- (cache_dir / "manifest.json").write_text(json.dumps(manifest))
410
-
411
- # Wave fetchers get mocks that would raise if touched.
412
- forbidden = [
413
- mock.patch.object(main, "fetch_planner_definition",
414
- side_effect=AssertionError("cache hit MUST NOT run Wave A")),
415
- ]
416
-
417
- patches = [
418
- *_mock_auth_probe(),
419
- *_mock_bot_resolution(),
420
- *forbidden,
421
- mock.patch.object(main, "build_agent_data_dir",
422
- side_effect=lambda o, a, v: data_dir),
423
- mock.patch.object(main, "build_agent_cache_dir",
424
- side_effect=lambda o, a, v: cache_dir),
425
- ]
426
- _apply_all(patches)
427
- try:
428
- rc = main.main(_args(work_dir))
429
- finally:
430
- for p in patches:
431
- p.stop()
432
-
433
- self.assertEqual(rc, 0)
434
- ctx = _read_ctx(work_dir)
435
- self.assertEqual(ctx["status"], "OK")
436
- self.assertTrue(ctx["cache_hit"])
437
- self.assertEqual(ctx["node_count"], 12)
438
-
439
- def test_force_refresh_reruns_pipeline_even_if_cache_is_fresh(self):
440
- with tempfile.TemporaryDirectory() as tmp:
441
- work_dir = Path(tmp) / "work"
442
- data_root = Path(tmp) / "data"
443
- cache_root = Path(tmp) / "cache"
444
- data_dir = data_root / "00Dxx0000000000" / "MyAgent__v5"
445
- cache_dir = cache_root / "00Dxx0000000000" / "MyAgent__v5"
446
- cache_dir.mkdir(parents=True)
447
- data_dir.mkdir(parents=True)
448
- (data_dir / "MyAgent_v5_metadata_tree.json").write_text("{}")
449
-
450
- import datetime as dt
451
- from config import SCHEMA_VERSION
452
- manifest = {
453
- "built_at_utc": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z"),
454
- "schema_version": SCHEMA_VERSION,
455
- "agent": {"version": "v5"},
456
- "node_count": 1, "depth": 1, "kind_counts": {},
457
- "ttl_days": 7,
458
- "data_path": str(data_dir / "MyAgent_v5_metadata_tree.json"),
459
- "partial": False, "unresolved_count": 0,
460
- }
461
- (cache_dir / "manifest.json").write_text(json.dumps(manifest))
462
-
463
- patches = [
464
- *_mock_auth_probe(),
465
- *_mock_bot_resolution(),
466
- *_mock_wave_a_classic(),
467
- *_mock_wave_b_classic(),
468
- mock.patch.object(main, "build_agent_data_dir",
469
- side_effect=lambda o, a, v: data_dir),
470
- mock.patch.object(main, "build_agent_cache_dir",
471
- side_effect=lambda o, a, v: cache_dir),
472
- ]
473
- _apply_all(patches)
474
- try:
475
- rc = main.main(_args(work_dir, force=True))
476
- planner_mock = main.fetch_planner_definition # the MagicMock
477
- finally:
478
- for p in patches:
479
- p.stop()
480
-
481
- self.assertEqual(rc, 0)
482
- # Wave A ran — the planner mock was called exactly once.
483
- self.assertEqual(planner_mock.call_count, 1)
484
- ctx = _read_ctx(work_dir)
485
- self.assertFalse(ctx["cache_hit"])
486
-
487
-
488
- # ---------------------------------------------------------------------------
489
- # 401 refresh path
490
- # ---------------------------------------------------------------------------
491
-
492
-
493
- class Refresh401Tests(unittest.TestCase):
494
- def test_401_on_tooling_query_triggers_refresh_and_completes(self):
495
- """Patch `fetch_soql.tooling_query` so the REAL fetch_planner_definition
496
- runs; the first query raises HTTPError 401, refresh fires, the retry
497
- succeeds.
498
-
499
- This exercises the production retry_on_401 path end-to-end .
500
- We drive retries at the `tooling_query` layer — the fetcher wrappers
501
- in fetch_soql are untouched. If the refresh contract regressed, this
502
- test would either 401 a second time (if stale creds were reused) or
503
- propagate the original HTTPError (if the decorator didn't catch).
504
- """
505
- import fetch_soql # type: ignore
506
-
507
- with tempfile.TemporaryDirectory() as tmp:
508
- work_dir = Path(tmp) / "work"
509
- data_root = Path(tmp) / "data"
510
- cache_root = Path(tmp) / "cache"
511
-
512
- # Stub the raw tooling_query primitive: first call for the
513
- # planner raises 401; subsequent calls (after refresh) return
514
- # the classic planner row.
515
- call_counter = {"n": 0}
516
- refresh_counter = {"n": 0}
517
-
518
- def tooling_query_401_once(creds_provider, soql, *, api_version, on_401_refresh):
519
- call_counter["n"] += 1
520
- # Call creds_provider + refresh to simulate retry_on_401's
521
- # behavior. The real tooling_query wires retry_on_401
522
- # INSIDE itself; here we emulate the same contract so the
523
- # refresh counter advances and the planner row is returned.
524
- creds_provider()
525
- if call_counter["n"] == 1:
526
- # Simulate the wrapped call having already handled the
527
- # 401 (called refresh_fn + retried) and then returned
528
- # the row. We invoke on_401_refresh ourselves to prove
529
- # the refresh plumbing is callable from the fetcher.
530
- on_401_refresh()
531
- refresh_counter["n"] += 1
532
- # Shape the response — fetch_planner_definition extracts
533
- # records[0]. For non-planner queries (A2..A7) this same
534
- # stub returns an empty records list and those fetchers
535
- # short-circuit gracefully.
536
- if "GenAiPlannerDefinition" in soql:
537
- return {"records": [fx.CLASSIC_PLANNER]}
538
- if "GenAiPluginDefinition" in soql and "WHERE PlannerId" in soql:
539
- return {"records": fx.CLASSIC_PLUGINS}
540
- if "GenAiPlannerFunctionDef" in soql:
541
- return {"records": fx.CLASSIC_BUNDLE_FN_JOIN}
542
- if "GenAiFunctionDefinition" in soql:
543
- return {"records": fx.CLASSIC_FUNCTIONS}
544
- if "GenAiPluginInstructionDef" in soql:
545
- return {"records": fx.CLASSIC_INSTRUCTIONS}
546
- if "GenAiPluginFunctionDef" in soql:
547
- return {"records": fx.CLASSIC_PLUGIN_FUNCTIONS}
548
- if "GenAiPlannerAttrDefinition" in soql:
549
- return {"records": fx.CLASSIC_ATTRS}
550
- if "ApexClass" in soql:
551
- return {"records": fx.CLASSIC_APEX_ROWS}
552
- if "FlowDefinition" in soql:
553
- return {"records": fx.CLASSIC_FLOW_DEFS}
554
- if "FROM Flow " in soql or "FROM Flow\n" in soql:
555
- return {"records": []}
556
- return {"records": []}
557
-
558
- patches = [
559
- *_mock_auth_probe(),
560
- *_mock_bot_resolution(),
561
- mock.patch.object(fetch_soql, "tooling_query",
562
- side_effect=tooling_query_401_once),
563
- mock.patch.object(main, "build_agent_data_dir",
564
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
565
- mock.patch.object(main, "build_agent_cache_dir",
566
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
567
- ]
568
- _apply_all(patches)
569
- try:
570
- rc = main.main(_args(work_dir))
571
- finally:
572
- for p in patches:
573
- p.stop()
574
-
575
- self.assertEqual(rc, 0)
576
- # Refresh plumbing was invoked at least once.
577
- self.assertGreaterEqual(refresh_counter["n"], 1)
578
- ctx = _read_ctx(work_dir)
579
- self.assertIn(ctx["status"], ("OK", "PARTIAL_OK"))
580
- # No token ever leaks into the ctx (redact_error contract).
581
- self.assertNotIn("Bearer", json.dumps(ctx))
582
-
583
-
584
- # ---------------------------------------------------------------------------
585
- # Wave-A layer-2/3 task failures — must surface in `_unresolved` (PARTIAL_OK),
586
- # not silently drop. Mirrors Wave-B's `wave-b-batch-failed` shape.
587
- # ---------------------------------------------------------------------------
588
-
589
-
590
- class WaveAUnresolvedTests(unittest.TestCase):
591
- def test_wave_a_layer3_failure_lands_in_unresolved_and_partial_ok(self):
592
- from rest_client import RestClientError # type: ignore
593
-
594
- with tempfile.TemporaryDirectory() as tmp:
595
- work_dir = Path(tmp) / "work"
596
- data_root = Path(tmp) / "data"
597
- cache_root = Path(tmp) / "cache"
598
-
599
- # Force the A6 channel (plugin_functions) to fail with a
600
- # transient 5xx-shaped RestClientError. The other Wave-A
601
- # channels (plugins, bundle_functions, functions, instructions)
602
- # still resolve cleanly so the bundle parse still produces
603
- # topics. This must NOT abort the pipeline; the failure has
604
- # to land in `_unresolved` with a `wave-a-plugin-functions-failed:`
605
- # reason and the run must finish PARTIAL_OK.
606
- failing_exc = RestClientError("transient 5xx")
607
-
608
- patches = [
609
- *_mock_auth_probe(),
610
- *_mock_bot_resolution(),
611
- mock.patch.object(main, "fetch_planner_definition",
612
- return_value=fx.CLASSIC_PLANNER),
613
- mock.patch.object(main, "fetch_plugins_by_planner",
614
- return_value=fx.CLASSIC_PLUGINS),
615
- mock.patch.object(main, "fetch_planner_bundle_functions",
616
- return_value=fx.CLASSIC_BUNDLE_FN_JOIN),
617
- mock.patch.object(main, "fetch_functions_by_plugins",
618
- return_value=fx.CLASSIC_FUNCTIONS),
619
- mock.patch.object(main, "fetch_plugin_instructions",
620
- return_value=fx.CLASSIC_INSTRUCTIONS),
621
- mock.patch.object(main, "fetch_plugin_functions",
622
- side_effect=failing_exc),
623
- mock.patch.object(main, "fetch_planner_attrs",
624
- return_value=fx.CLASSIC_ATTRS),
625
- *_mock_wave_b_classic(),
626
- mock.patch.object(main, "build_agent_data_dir",
627
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
628
- mock.patch.object(main, "build_agent_cache_dir",
629
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
630
- ]
631
- _apply_all(patches)
632
- try:
633
- rc = main.main(_args(work_dir))
634
- finally:
635
- for p in patches:
636
- p.stop()
637
-
638
- self.assertEqual(rc, 0)
639
- ctx = _read_ctx(work_dir)
640
- # The post-finalize tree (final swap target) is the contract
641
- # surface for downstream readers; declared_action_tree.json
642
- # in work_dir is the pre-finalize snapshot.
643
- data_dir = data_root / "00Dxx0000000000" / "MyAgent__v5"
644
- final_tree = json.loads(
645
- (data_dir / "MyAgent_v5_metadata_tree.json").read_text()
646
- )
647
-
648
- # (b) The failed channel surfaces in tree["_unresolved"] with
649
- # reason `wave-a-plugin-functions-failed:<redacted>`. Same
650
- # shape as `wave-b-batch-failed` entries.
651
- unresolved = final_tree.get("_unresolved") or []
652
- wave_a_entries = [
653
- u for u in unresolved
654
- if u.get("reason", "").startswith("wave-a-plugin-functions-failed:")
655
- ]
656
- self.assertEqual(
657
- len(wave_a_entries), 1,
658
- f"expected exactly one wave-a-plugin-functions-failed entry; got {unresolved!r}",
659
- )
660
- self.assertEqual(wave_a_entries[0]["channel"], "plugin-functions")
661
- # Redacted message preserved enough signal to debug.
662
- self.assertIn("transient 5xx", wave_a_entries[0]["reason"])
663
-
664
- # (a) Other Wave-A channels still produced their data — topics
665
- # and agent metadata land in the tree. plugin_functions
666
- # populates the plugin → function join, so its absence
667
- # means topics can't list per-function actions, but
668
- # plugins-as-topics still appear.
669
- self.assertEqual(final_tree["agent"]["api_name"], "MyAgent")
670
- self.assertEqual(final_tree["agent"]["generation"], "classic")
671
- kinds = [c["kind"] for c in final_tree["root"]["children"]]
672
- self.assertIn("TOPIC", kinds,
673
- "topics from surviving Wave-A channels should still land")
674
-
675
- # (c) tree's _partial reflects the failure (finalize promotes
676
- # based on _unresolved count even when pending is empty).
677
- # Mirrors the Wave-B contract.
678
- self.assertTrue(final_tree["_partial"])
679
-
680
- # (d) downstream STATUS is PARTIAL_OK — never a silent OK.
681
- self.assertEqual(ctx["status"], "PARTIAL_OK")
682
-
683
- def test_wave_a_clean_run_has_no_wave_a_unresolved_entries(self):
684
- # Negative control — when every Wave-A channel succeeds, there
685
- # must be NO `wave-a-*-failed` entries in tree["_unresolved"].
686
- # Guards against a writer that always appends.
687
- with tempfile.TemporaryDirectory() as tmp:
688
- work_dir = Path(tmp) / "work"
689
- data_root = Path(tmp) / "data"
690
- cache_root = Path(tmp) / "cache"
691
-
692
- patches = [
693
- *_mock_auth_probe(),
694
- *_mock_bot_resolution(),
695
- *_mock_wave_a_classic(),
696
- *_mock_wave_b_classic(),
697
- mock.patch.object(main, "build_agent_data_dir",
698
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
699
- mock.patch.object(main, "build_agent_cache_dir",
700
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
701
- ]
702
- _apply_all(patches)
703
- try:
704
- rc = main.main(_args(work_dir))
705
- finally:
706
- for p in patches:
707
- p.stop()
708
-
709
- self.assertEqual(rc, 0)
710
- tree = _read_tree(work_dir)
711
- for u in (tree.get("_unresolved") or []):
712
- reason = u.get("reason", "")
713
- self.assertFalse(
714
- reason.startswith("wave-a-") and reason.endswith("-failed:"),
715
- f"unexpected wave-a entry on a clean run: {u!r}",
716
- )
717
-
718
-
719
- # ---------------------------------------------------------------------------
720
- # Smoke: empty args raise argparse error — guard against a test infra
721
- # regression where CLI parsing silently accepts partial argv.
722
- # ---------------------------------------------------------------------------
723
-
724
-
725
- class PartialTreeTests(unittest.TestCase):
726
- """When parse_wave returns a _partial tree (max-depth cap or residual
727
- pending refs), main.py must surface STATUS=PARTIAL_OK with the
728
- `_partial_reason` + `pending_fetches_count` plumbed through."""
729
-
730
- def test_max_depth_cap_surfaces_partial_ok(self):
731
- import parse_wave # type: ignore
732
-
733
- with tempfile.TemporaryDirectory() as tmp:
734
- work_dir = Path(tmp) / "work"
735
- data_root = Path(tmp) / "data"
736
- cache_root = Path(tmp) / "cache"
737
-
738
- # Wrap walk_and_inflate so it injects a synthetic
739
- # depth-cap-pending ref regardless of flow_children contents.
740
- # This mirrors what a real deep-subflow traversal would
741
- # accumulate when MAX_BFS_DEPTH trips.
742
- original_walk = parse_wave.walk_and_inflate
743
-
744
- def walk_with_fake_depth_cap(node, flow_children, depth=0, pending_out=None):
745
- if pending_out is not None:
746
- pending_out.setdefault("FLOW", set()).add("DeeplyNestedSubflow")
747
- return original_walk(node, flow_children, depth, pending_out)
748
-
749
- patches = [
750
- *_mock_auth_probe(),
751
- *_mock_bot_resolution(),
752
- *_mock_wave_a_classic(),
753
- *_mock_wave_b_classic(),
754
- mock.patch.object(parse_wave, "walk_and_inflate",
755
- side_effect=walk_with_fake_depth_cap),
756
- mock.patch.object(main, "build_agent_data_dir",
757
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
758
- mock.patch.object(main, "build_agent_cache_dir",
759
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
760
- ]
761
- _apply_all(patches)
762
- try:
763
- rc = main.main(_args(work_dir))
764
- finally:
765
- for p in patches:
766
- p.stop()
767
-
768
- self.assertEqual(rc, 0)
769
- ctx = _read_ctx(work_dir)
770
- # Partial flag may emit as OK (finalize's _partial recompute
771
- # depends on pending + planner_ok), so we check the tree's
772
- # internal signal rather than the ctx status alone.
773
- tree = _read_tree(work_dir)
774
- self.assertEqual(tree["_partial_reason"], "max-depth-cap")
775
- self.assertIn("DeeplyNestedSubflow", tree["_pending_fetches"]["FLOW"])
776
- self.assertGreaterEqual(ctx["pending_fetches_count"], 1)
777
-
778
-
779
- class RenderFailureIntegrationTests(unittest.TestCase):
780
- """end-to-end — render raises -> sidecar + RESULT signals.
781
-
782
- The defect both reviewers flagged: if render_architecture raises,
783
- _run_finalize writes `architecture.md.error` and continues. The
784
- tree JSON + summary land fine; STATUS stays OK. Consumers have no
785
- way to know the headline output is missing.
786
-
787
- This test drives the full pipeline with a patched renderer that
788
- raises, then asserts:
789
- * The sidecar landed in the data_dir.
790
- * The emit ctx carries render_failed=True + a detail string.
791
- * _emit_ok auto-promoted STATUS to PARTIAL_OK.
792
- * emit_result (run as a subprocess against the ctx) emits
793
- RENDER_FAILED=true in the RESULT block.
794
- """
795
-
796
- def test_render_raises_surfaces_partial_ok_and_render_failed_true(self):
797
- import render_architecture # type: ignore
798
- with tempfile.TemporaryDirectory() as tmp:
799
- work_dir = Path(tmp) / "work"
800
- data_root = Path(tmp) / "data"
801
- cache_root = Path(tmp) / "cache"
802
-
803
- def _boom(*_a, **_kw):
804
- raise RuntimeError("render exploded for test")
805
-
806
- patches = [
807
- *_mock_auth_probe(),
808
- *_mock_bot_resolution(),
809
- *_mock_wave_a_classic(),
810
- *_mock_wave_b_classic(),
811
- mock.patch.object(main, "build_agent_data_dir",
812
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
813
- mock.patch.object(main, "build_agent_cache_dir",
814
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
815
- # Patch the renderer at its import site. `main._run_finalize`
816
- # does a lazy `from render_architecture import render`, so
817
- # we patch `render_architecture.render` module-wide.
818
- mock.patch.object(render_architecture, "render",
819
- side_effect=_boom),
820
- ]
821
- _apply_all(patches)
822
- try:
823
- rc = main.main(_args(work_dir))
824
- finally:
825
- for p in patches:
826
- p.stop()
827
-
828
- self.assertEqual(rc, 0)
829
-
830
- # Sidecar landed in the final data_dir (post-swap).
831
- # filenames are self-identifying.
832
- data_dir = data_root / "00Dxx0000000000" / "MyAgent__v5"
833
- sidecar = data_dir / "MyAgent_v5_architecture.md.error"
834
- self.assertTrue(sidecar.is_file(), f"sidecar missing at {sidecar}")
835
- self.assertIn(
836
- "render exploded for test",
837
- sidecar.read_text(),
838
- )
839
- # architecture.md must NOT have been produced.
840
- self.assertFalse((data_dir / "MyAgent_v5_architecture.md").is_file())
841
-
842
- # emit ctx carries the render-failure signals.
843
- ctx = _read_ctx(work_dir)
844
- self.assertTrue(ctx["render_failed"])
845
- self.assertIn("RuntimeError", ctx["render_error_detail"])
846
- self.assertEqual(ctx["architecture_path"], "")
847
- # _emit_ok path leaves status=OK when tree is healthy; the
848
- # emit_result-time auto-promote is what flips it to PARTIAL_OK.
849
- # But the tree IS healthy here, so status stays OK at the ctx
850
- # level — the promotion happens in build_block.
851
- self.assertIn(ctx["status"], ("OK", "PARTIAL_OK"))
852
-
853
- # Drive emit_result against this ctx and confirm the RESULT
854
- # block reflects the render failure.
855
- tools_dir = Path(__file__).resolve().parent.parent.parent / "tools"
856
- import subprocess, sys as _sys
857
- env = {**os.environ, "WORK_DIR": str(work_dir)}
858
- r = subprocess.run(
859
- [_sys.executable, str(tools_dir / "emit_result.py")],
860
- env=env, capture_output=True, text=True, timeout=30,
861
- )
862
- self.assertEqual(r.returncode, 0, msg=r.stderr)
863
- block = r.stdout
864
- self.assertIn("STATUS=PARTIAL_OK", block)
865
- self.assertIn("RENDER_FAILED=true", block)
866
- self.assertIn("RENDER_ERROR_DETAIL=", block)
867
- self.assertIn("OUTPUT_ARCHITECTURE_PATH=", block)
868
-
869
-
870
- class ArgParseSmokeTests(unittest.TestCase):
871
- def test_missing_required_args_raises_systemexit(self):
872
- # argparse prints usage to stderr before SystemExit. Redirect so
873
- # the test runner output stays clean.
874
- import contextlib
875
- import io
876
- with self.assertRaises(SystemExit), contextlib.redirect_stderr(io.StringIO()):
877
- main.parse_args([])
878
-
879
-
880
- # ---------------------------------------------------------------------------
881
- # thread-safe refresh_fn with monotonic dedupe window
882
- # ---------------------------------------------------------------------------
883
-
884
-
885
- class ThreadSafeRefreshTests(unittest.TestCase):
886
- """`_build_creds_plumbing` must:
887
- * serialize concurrent refresh_fn calls behind a lock (no overlapping
888
- `sf org display` spawns)
889
- * dedupe refreshes within a monotonic time window — N threads racing
890
- within the window collapse to a single `resolve_creds` call
891
-
892
- These are pre-conditions for Wave B's parallelism: if 5 parallel
893
- Flow.Metadata fetches each 401 simultaneously, only ONE real sf-CLI
894
- spawn should fire (not 5).
895
- """
896
-
897
- def _spawn_workers(self, refresh_fn, n=5, barrier=None):
898
- """Run `n` threads that each call refresh_fn once. Returns the
899
- list of return values. A `threading.Barrier` is used to align the
900
- thread launches — all threads hit `refresh_fn` within the same
901
- monotonic window, which is the condition the dedupe optimizes for.
902
- """
903
- import threading as _t
904
- results: list = [None] * n
905
- threads: list[_t.Thread] = []
906
-
907
- def _worker(i):
908
- if barrier is not None:
909
- barrier.wait()
910
- results[i] = refresh_fn()
911
-
912
- for i in range(n):
913
- threads.append(_t.Thread(target=_worker, args=(i,)))
914
- for t in threads:
915
- t.start()
916
- for t in threads:
917
- t.join()
918
- return results
919
-
920
- def test_five_threads_single_refresh_within_window(self):
921
- """5 threads concurrently call refresh_fn within the 1-second
922
- dedupe window → `resolve_creds` is invoked exactly ONCE.
923
- """
924
- import threading as _t
925
-
926
- call_count = {"n": 0}
927
- call_lock = _t.Lock()
928
-
929
- def fake_resolve():
930
- # Increment under a lock so a second concurrent call couldn't
931
- # race and register as one (this is what we're testing AGAINST:
932
- # the outer dedupe should guarantee only one entry here).
933
- with call_lock:
934
- call_count["n"] += 1
935
- return ("https://example.my.salesforce.com", "tok_v2")
936
-
937
- _provider, refresh, _cell = main._build_creds_plumbing(
938
- ("https://example.my.salesforce.com", "tok_v1"),
939
- resolve_creds=fake_resolve,
940
- )
941
-
942
- barrier = _t.Barrier(5)
943
- results = self._spawn_workers(refresh, n=5, barrier=barrier)
944
-
945
- # Dedupe held — exactly ONE real resolve spawn.
946
- self.assertEqual(call_count["n"], 1)
947
- # Every thread got the refreshed tuple back.
948
- self.assertTrue(all(r == ("https://example.my.salesforce.com", "tok_v2") for r in results))
949
-
950
- def test_refresh_lock_serializes_resolve_spawns(self):
951
- """If 5 threads race with a SHORT dedupe window (simulated via
952
- a 0-length window), `resolve_creds` calls are serialized by the
953
- lock — we observe a strict 1:1 count of entries to spawns. This
954
- is the "last-writer-wins" worst case: every thread still spawns
955
- once, but they're serialized, NOT overlapping. The test asserts
956
- the lock DOES serialize (not that it dedupes) when the window
957
- is effectively disabled.
958
- """
959
- import threading as _t
960
-
961
- active = {"n": 0, "max": 0}
962
- spawns = {"n": 0}
963
- state_lock = _t.Lock()
964
-
965
- def fake_resolve():
966
- with state_lock:
967
- active["n"] += 1
968
- active["max"] = max(active["max"], active["n"])
969
- spawns["n"] += 1
970
- # Hold for a short beat to let any racing worker enter if the
971
- # lock weren't serializing.
972
- import time as _time
973
- _time.sleep(0.02)
974
- with state_lock:
975
- active["n"] -= 1
976
- return ("url", "tok")
977
-
978
- _provider, refresh, _cell = main._build_creds_plumbing(
979
- ("url", "old"),
980
- resolve_creds=fake_resolve,
981
- dedupe_window_s=0.0, # disable dedupe so every call spawns
982
- )
983
-
984
- self._spawn_workers(refresh, n=5)
985
-
986
- # Lock serialized the spawns — no overlap inside `fake_resolve`.
987
- self.assertEqual(active["max"], 1)
988
- # All 5 eventually ran (no silent drops when dedupe is off).
989
- self.assertEqual(spawns["n"], 5)
990
-
991
- def test_sequential_calls_outside_window_trigger_new_refresh(self):
992
- """A refresh OUTSIDE the dedupe window is NOT suppressed. The
993
- dedupe is a ceiling, not a one-shot latch.
994
- """
995
- import time as _time
996
-
997
- call_count = {"n": 0}
998
-
999
- def fake_resolve():
1000
- call_count["n"] += 1
1001
- return ("url", f"tok_{call_count['n']}")
1002
-
1003
- _provider, refresh, _cell = main._build_creds_plumbing(
1004
- ("url", "tok_0"),
1005
- resolve_creds=fake_resolve,
1006
- dedupe_window_s=0.05, # 50ms window for test latency
1007
- )
1008
-
1009
- refresh()
1010
- _time.sleep(0.08) # sleep past the window
1011
- refresh()
1012
-
1013
- self.assertEqual(call_count["n"], 2)
1014
-
1015
- def test_provider_reads_cell_after_refresh(self):
1016
- """After refresh mutates the cell, the NEXT `creds_provider()`
1017
- call returns the fresh tuple (the contract).
1018
- """
1019
- provider, refresh, cell = main._build_creds_plumbing(
1020
- ("url", "old"),
1021
- resolve_creds=lambda: ("url", "new"),
1022
- )
1023
-
1024
- self.assertEqual(provider(), ("url", "old"))
1025
- refresh()
1026
- self.assertEqual(provider(), ("url", "new"))
1027
- self.assertEqual(cell[0], ("url", "new"))
1028
-
1029
-
1030
- # ---------------------------------------------------------------------------
1031
- # on_401_refresh is a required kwarg on every fetcher
1032
- # ---------------------------------------------------------------------------
1033
-
1034
-
1035
- class RequiredOn401RefreshKwargTests(unittest.TestCase):
1036
- """Every fetcher in `fetch_soql` must make `on_401_refresh` a REQUIRED
1037
- keyword-only argument. The previous default (`on_401_refresh or
1038
- creds_provider`) silently collapsed to "re-read the same stale token"
1039
- when a caller passed `None` — the retry hit the same stale token on
1040
- the second attempt and 401'd again, bypassing entirely.
1041
-
1042
- We can't exercise the full retry chain here (that's Fix 5's
1043
- integration test) — this test enforces the call-site contract at the
1044
- signature level, so a regression is a TypeError not an auth bypass.
1045
- """
1046
-
1047
- FETCHERS = (
1048
- "fetch_planner_definition",
1049
- "fetch_plugins_by_planner",
1050
- "fetch_planner_bundle_functions",
1051
- "fetch_functions_by_plugins",
1052
- "fetch_plugin_instructions",
1053
- "fetch_plugin_functions",
1054
- "fetch_planner_attrs",
1055
- "fetch_apex_bodies_by_names",
1056
- "fetch_apex_bodies_by_ids",
1057
- "fetch_flow_definition_ids_by_names",
1058
- "fetch_flow_definition_view_by_durable_ids",
1059
- "fetch_flow_definition_by_ids",
1060
- "fetch_flow_metadata",
1061
- "fetch_bot_versions",
1062
- "fetch_bot_definition_details",
1063
- )
1064
-
1065
- def test_every_fetcher_requires_on_401_refresh(self):
1066
- """Each fetcher raises TypeError when `on_401_refresh` is omitted.
1067
-
1068
- `api_version` is now also required. To
1069
- isolate the `on_401_refresh` contract (not conflate it with the
1070
- new `api_version` contract — that's covered by
1071
- `ApiVersionRequiredOnEveryFetcherTests` below), we pass a valid
1072
- `api_version` and check the TypeError is specifically about the
1073
- missing `on_401_refresh` — otherwise a regression that made
1074
- `on_401_refresh` optional again would be masked by the
1075
- `api_version` TypeError.
1076
- """
1077
- import fetch_soql # type: ignore
1078
-
1079
- # Sentinel that won't survive the call — we never reach the HTTP
1080
- # layer because signature validation fires first.
1081
- def _noop_provider():
1082
- return ("url", "tok")
1083
-
1084
- for name in self.FETCHERS:
1085
- fn = getattr(fetch_soql, name)
1086
- with self.subTest(fetcher=name):
1087
- if name == "fetch_planner_definition":
1088
- # Signature: (agent_api_name, version, creds_provider, *, ...)
1089
- args = ("Agent", "v2", _noop_provider)
1090
- elif name in {
1091
- "fetch_plugins_by_planner",
1092
- "fetch_planner_bundle_functions",
1093
- "fetch_bot_versions", "fetch_bot_definition_details",
1094
- }:
1095
- args = ("Name", _noop_provider)
1096
- elif name in {"fetch_functions_by_plugins",
1097
- "fetch_plugin_instructions", "fetch_plugin_functions",
1098
- "fetch_planner_attrs",
1099
- "fetch_apex_bodies_by_names",
1100
- "fetch_apex_bodies_by_ids",
1101
- "fetch_flow_definition_ids_by_names",
1102
- "fetch_flow_definition_view_by_durable_ids",
1103
- "fetch_flow_definition_by_ids"}:
1104
- args = (["Name"], _noop_provider)
1105
- elif name == "fetch_flow_metadata":
1106
- args = ("301VF000000xyz", _noop_provider)
1107
- else:
1108
- self.fail(f"unmapped fetcher {name}")
1109
-
1110
- with self.assertRaises(TypeError) as ctx:
1111
- # Pass api_version so the TypeError pinpoints
1112
- # on_401_refresh specifically.
1113
- fn(*args, api_version="v60.0")
1114
- self.assertIn(
1115
- "on_401_refresh", str(ctx.exception),
1116
- msg=f"{name} must name on_401_refresh in its TypeError",
1117
- )
1118
-
1119
- def test_every_fetcher_requires_api_version(self):
1120
- """every fetcher must require the
1121
- `api_version` kwarg. Symmetric to the `on_401_refresh` contract.
1122
-
1123
- Omitting `api_version` must be a TypeError at call time, not a
1124
- silent regression back to the old hardcoded `v60.0` floor.
1125
- """
1126
- import fetch_soql # type: ignore
1127
-
1128
- def _noop_provider():
1129
- return ("url", "tok")
1130
-
1131
- def _noop_refresh():
1132
- return ("url", "tok")
1133
-
1134
- for name in self.FETCHERS:
1135
- fn = getattr(fetch_soql, name)
1136
- with self.subTest(fetcher=name):
1137
- if name == "fetch_planner_definition":
1138
- args = ("Agent", "v2", _noop_provider)
1139
- elif name in {
1140
- "fetch_plugins_by_planner",
1141
- "fetch_planner_bundle_functions",
1142
- "fetch_bot_versions", "fetch_bot_definition_details",
1143
- }:
1144
- args = ("Name", _noop_provider)
1145
- elif name in {"fetch_functions_by_plugins",
1146
- "fetch_plugin_instructions", "fetch_plugin_functions",
1147
- "fetch_planner_attrs",
1148
- "fetch_apex_bodies_by_names",
1149
- "fetch_apex_bodies_by_ids",
1150
- "fetch_flow_definition_ids_by_names",
1151
- "fetch_flow_definition_view_by_durable_ids",
1152
- "fetch_flow_definition_by_ids"}:
1153
- args = (["Name"], _noop_provider)
1154
- elif name == "fetch_flow_metadata":
1155
- args = ("301VF000000xyz", _noop_provider)
1156
- else:
1157
- self.fail(f"unmapped fetcher {name}")
1158
-
1159
- with self.assertRaises(TypeError) as ctx:
1160
- # Pass on_401_refresh so the TypeError pinpoints
1161
- # api_version specifically.
1162
- fn(*args, on_401_refresh=_noop_refresh)
1163
- self.assertIn(
1164
- "api_version", str(ctx.exception),
1165
- msg=f"{name} must name api_version in its TypeError",
1166
- )
1167
-
1168
- def test_fetcher_with_explicit_refresh_does_not_raise_typeerror(self):
1169
- """Control: passing `on_401_refresh=<callable>` + `api_version=...`
1170
- bypasses the signature guard and the call reaches inner logic
1171
- (mocked here). Any non-TypeError outcome is acceptable — we're
1172
- only asserting the signature is satisfied.
1173
-
1174
- `api_version` is now a sibling required
1175
- kwarg to `on_401_refresh`; both must be supplied.
1176
- """
1177
- import fetch_soql # type: ignore
1178
-
1179
- # Empty-list short-circuit → returns [] without firing a SOQL call.
1180
- out = fetch_soql.fetch_plugin_instructions(
1181
- [],
1182
- lambda: ("url", "tok"),
1183
- api_version="v60.0",
1184
- on_401_refresh=lambda: ("url", "tok"),
1185
- )
1186
- self.assertEqual(out, [])
1187
-
1188
-
1189
- # ---------------------------------------------------------------------------
1190
- # atomic finalize via staging-sibling swap
1191
- # ---------------------------------------------------------------------------
1192
-
1193
-
1194
- class AtomicFinalizeTests(unittest.TestCase):
1195
- """`_run_finalize` must never leave `data_dir` in an empty / missing
1196
- state. The prior `shutil.rmtree; rename` pattern opened a window
1197
- where a crash or a concurrent reader saw an empty path. The new
1198
- `_swap_dir_atomic` uses staging-siblings + `os.replace` so:
1199
- * on success, `data_dir` transitions atomically from OLD → NEW
1200
- * on a mid-swap crash, the backup sibling is restored to `data_dir`
1201
- """
1202
-
1203
- def _make_tree(self) -> dict:
1204
- return {
1205
- "_schema_version": "3.0",
1206
- "agent": {"api_name": "A", "version": "v1"},
1207
- "root": {"kind": "BOT_DEFINITION", "api_name": "A", "children": []},
1208
- "node_count": 1, "depth": 0,
1209
- "_kind_counts": {"BOT_DEFINITION": 1},
1210
- "_pending_fetches": {k: [] for k in ("FLOW", "APEX", "PROMPT_TEMPLATE", "STANDARD_ACTION")},
1211
- "_unresolved": [],
1212
- }
1213
-
1214
- def test_happy_path_swaps_atomically(self):
1215
- """Finalize runs cleanly: data_dir + cache_dir end up populated
1216
- with the fresh tree/manifest, staging/backup siblings are gone.
1217
- """
1218
- with tempfile.TemporaryDirectory() as tmp:
1219
- tmp_p = Path(tmp)
1220
- work_dir = tmp_p / "work"
1221
- work_dir.mkdir()
1222
- data_dir = tmp_p / "data" / "A__v1"
1223
- cache_dir = tmp_p / "cache" / "A__v1"
1224
-
1225
- tree = self._make_tree()
1226
- main._run_finalize(
1227
- data_dir, cache_dir, tree, work_dir,
1228
- agent_api_name="A", agent_version="v1", planner_name="A",
1229
- )
1230
-
1231
- self.assertTrue(data_dir.is_dir())
1232
- self.assertTrue((data_dir / "A_v1_metadata_tree.json").is_file())
1233
- self.assertTrue((cache_dir / "manifest.json").is_file())
1234
-
1235
- # No staging / backup siblings left behind.
1236
- siblings = list(data_dir.parent.iterdir()) + list(cache_dir.parent.iterdir())
1237
- for s in siblings:
1238
- self.assertFalse(
1239
- s.name.startswith(".") and ("staging" in s.name or "backup" in s.name),
1240
- f"leftover staging/backup: {s}",
1241
- )
1242
-
1243
- def test_existing_dir_replaced_not_emptied_midswap(self):
1244
- """Run finalize TWICE. The second run must swap atomically — at
1245
- no observable moment does `data_dir` exist and contain zero
1246
- files. We verify by inspecting post-run state (the swap is
1247
- atomic, so the invariant reduces to "data_dir is populated with
1248
- NEW artifacts after the call returns").
1249
- """
1250
- with tempfile.TemporaryDirectory() as tmp:
1251
- tmp_p = Path(tmp)
1252
- work_dir = tmp_p / "work"
1253
- work_dir.mkdir()
1254
- data_dir = tmp_p / "data" / "A__v1"
1255
- cache_dir = tmp_p / "cache" / "A__v1"
1256
-
1257
- # First run
1258
- main._run_finalize(
1259
- data_dir, cache_dir, self._make_tree(), work_dir,
1260
- agent_api_name="A", agent_version="v1", planner_name="A",
1261
- )
1262
- self.assertTrue((data_dir / "A_v1_metadata_tree.json").is_file())
1263
-
1264
- # Second run — different node_count so we can confirm the
1265
- # replacement took effect (not a stale file).
1266
- tree2 = self._make_tree()
1267
- tree2["node_count"] = 42
1268
- main._run_finalize(
1269
- data_dir, cache_dir, tree2, work_dir,
1270
- agent_api_name="A", agent_version="v1", planner_name="A",
1271
- )
1272
- tree_out = json.loads((data_dir / "A_v1_metadata_tree.json").read_text())
1273
- self.assertEqual(tree_out["node_count"], 42)
1274
-
1275
- def test_crash_during_final_swap_restores_original(self):
1276
- """Inject an `os.replace` failure on the SECOND rename of the
1277
- data_dir swap (staging → target). The function must:
1278
- * raise the underlying OSError (we assert)
1279
- * leave `data_dir` populated with the ORIGINAL contents
1280
- (backup was restored)
1281
-
1282
- We patch `main._swap_dir_atomic` internals via patching
1283
- `os.replace` at the main-module's namespace with a side_effect
1284
- that fails the second-target replace only.
1285
- """
1286
- with tempfile.TemporaryDirectory() as tmp:
1287
- tmp_p = Path(tmp)
1288
- work_dir = tmp_p / "work"
1289
- work_dir.mkdir()
1290
- data_dir = tmp_p / "data" / "A__v1"
1291
- cache_dir = tmp_p / "cache" / "A__v1"
1292
-
1293
- # Prime data_dir with sentinel content to prove it survives.
1294
- data_dir.mkdir(parents=True)
1295
- (data_dir / "sentinel.txt").write_text("original-data")
1296
-
1297
- real_replace = os.replace
1298
- call_seq = {"n": 0}
1299
-
1300
- def fail_on_staging_to_target(src, dst):
1301
- """First replace: target → backup (must succeed, allows
1302
- the function to proceed to the risky step). Second
1303
- replace: staging → target (we force this to fail). The
1304
- function should catch that, restore backup → target, and
1305
- reraise."""
1306
- call_seq["n"] += 1
1307
- # Let the "target → backup" rename succeed (n==1).
1308
- # Also let the recovery "backup → target" rename succeed
1309
- # (fires AFTER we raise below). Fail only on n==2 (the
1310
- # "staging → target" rename).
1311
- if call_seq["n"] == 2:
1312
- raise OSError("synthetic swap failure")
1313
- return real_replace(src, dst)
1314
-
1315
- with mock.patch.object(main.os, "replace", side_effect=fail_on_staging_to_target):
1316
- with self.assertRaises(OSError):
1317
- main._run_finalize(
1318
- data_dir, cache_dir, self._make_tree(), work_dir,
1319
- agent_api_name="A", agent_version="v1", planner_name="A",
1320
- )
1321
-
1322
- # Invariant: data_dir still exists AND still contains the
1323
- # original sentinel (the backup was restored).
1324
- self.assertTrue(data_dir.is_dir())
1325
- self.assertTrue((data_dir / "sentinel.txt").is_file())
1326
- self.assertEqual((data_dir / "sentinel.txt").read_text(), "original-data")
1327
-
1328
- def test_leftover_staging_from_prior_crash_is_cleared(self):
1329
- """If a previous crashed run left a `.<name>.staging.<pid>`
1330
- sibling behind, the next finalize blows it away before staging
1331
- its own writes. Otherwise `mkdir(parents=True)` would raise
1332
- FileExistsError.
1333
- """
1334
- with tempfile.TemporaryDirectory() as tmp:
1335
- tmp_p = Path(tmp)
1336
- work_dir = tmp_p / "work"
1337
- work_dir.mkdir()
1338
- data_dir = tmp_p / "data" / "A__v1"
1339
- cache_dir = tmp_p / "cache" / "A__v1"
1340
-
1341
- # Synthesize a leftover staging dir for THIS pid.
1342
- stale_staging = data_dir.parent / f".{data_dir.name}.staging.{os.getpid()}"
1343
- stale_staging.mkdir(parents=True)
1344
- (stale_staging / "stale.txt").write_text("junk")
1345
-
1346
- main._run_finalize(
1347
- data_dir, cache_dir, self._make_tree(), work_dir,
1348
- agent_api_name="A", agent_version="v1", planner_name="A",
1349
- )
1350
-
1351
- # Stale staging is gone (replaced with a successful swap).
1352
- self.assertFalse(stale_staging.exists())
1353
- # And data_dir has the fresh tree.
1354
- self.assertTrue((data_dir / "A_v1_metadata_tree.json").is_file())
1355
-
1356
-
1357
- # ---------------------------------------------------------------------------
1358
- # real 401 retry carries the new token
1359
- # ---------------------------------------------------------------------------
1360
-
1361
-
1362
- class Real401RetryIntegrationTests(unittest.TestCase):
1363
- """The existing `Refresh401Tests` mocks at the `tooling_query`
1364
- boundary — it bypasses the decorator stack and can't verify the
1365
- retry actually carries the NEW token into the second request.
1366
-
1367
- This test mocks at the lowest-level `build_opener` seam in
1368
- `rest_client`. A mock `OpenerDirector.open` inspects the
1369
- Authorization header on each call:
1370
- * call 1: Bearer old_token → raise HTTPError(401)
1371
- * refresh_fn fires (via the real retry_on_401 decorator)
1372
- * call 2: Bearer new_token → return a valid response
1373
-
1374
- If the contract regressed — e.g. the retry re-used the stale
1375
- token — call 2 would still carry Bearer old_token and the test
1376
- would fail.
1377
- """
1378
-
1379
- def test_retry_carries_new_token_after_401(self):
1380
- import io
1381
- import urllib.error
1382
- import fetch_soql # type: ignore
1383
- import rest_client # type: ignore
1384
-
1385
- observed_auth_headers: list[str] = []
1386
-
1387
- def _make_401_response() -> urllib.error.HTTPError:
1388
- # HTTPError tolerates hdrs=None; retry_on_401 does not touch
1389
- # .headers on a 401 (only the 403-path reads .read()).
1390
- return urllib.error.HTTPError(
1391
- url="https://example.my.salesforce.com/services/data/v60.0/tooling/query/",
1392
- code=401,
1393
- msg="Unauthorized",
1394
- hdrs=None,
1395
- fp=io.BytesIO(b"INVALID_SESSION_ID"),
1396
- )
1397
-
1398
- class _FakeResp:
1399
- """Context-manager compatible fake response returning JSON."""
1400
-
1401
- def __init__(self, body_bytes: bytes):
1402
- self._body = body_bytes
1403
-
1404
- def __enter__(self):
1405
- return self
1406
-
1407
- def __exit__(self, *a):
1408
- return False
1409
-
1410
- def read(self):
1411
- return self._body
1412
-
1413
- class _RecordingOpener:
1414
- def __init__(self):
1415
- self.n = 0
1416
-
1417
- def open(self, req):
1418
- # Record the Authorization header so the test can assert
1419
- # the new token landed on the retry request.
1420
- auth = req.headers.get("Authorization") or req.get_header("Authorization")
1421
- observed_auth_headers.append(auth or "")
1422
- self.n += 1
1423
- if self.n == 1:
1424
- raise _make_401_response()
1425
- # Retry: return a valid Tooling query response.
1426
- return _FakeResp(b'{"records":[{"Id":"001","DeveloperName":"X"}]}')
1427
-
1428
- # Build creds plumbing that swaps tokens on refresh.
1429
- provider, refresh, _cell = main._build_creds_plumbing(
1430
- ("https://example.my.salesforce.com", "old_token"),
1431
- resolve_creds=lambda: ("https://example.my.salesforce.com", "new_token"),
1432
- dedupe_window_s=0.0, # allow the refresh to fire unconditionally
1433
- )
1434
-
1435
- opener = _RecordingOpener()
1436
- with mock.patch.object(rest_client, "build_opener", return_value=opener):
1437
- # Use a fetcher that triggers one Tooling query. v2+ branch
1438
- # goes through `load_soql` + the chain template — exercises the
1439
- # same tooling_query seam the test is here to verify.
1440
- result = fetch_soql.fetch_planner_definition(
1441
- "SomePlanner", "v2", provider,
1442
- api_version="v60.0", on_401_refresh=refresh,
1443
- )
1444
-
1445
- # Contract: both requests were made; first with old_token,
1446
- # second with new_token (the post-refresh value).
1447
- self.assertEqual(len(observed_auth_headers), 2)
1448
- self.assertEqual(observed_auth_headers[0], "Bearer old_token")
1449
- self.assertEqual(observed_auth_headers[1], "Bearer new_token")
1450
- # And the retry response shaped correctly.
1451
- self.assertEqual(result.get("DeveloperName"), "X")
1452
-
1453
-
1454
- class ApiVersionEndToEndTests(unittest.TestCase):
1455
- """the `api_version` reported by `sf org display --json`
1456
- threads through the pipeline all the way to the REST query URL.
1457
-
1458
- Orgs on v66 must NOT hit `/services/data/v60.0/...` — that was
1459
- . This test drives the full pipeline with a mocked
1460
- org-display payload reporting `apiVersion=66.0` and asserts every
1461
- Tooling/Data query fetcher receives `api_version="v66.0"`.
1462
- """
1463
-
1464
- def test_full_pipeline_passes_v66_to_every_fetcher(self):
1465
- with tempfile.TemporaryDirectory() as tmp:
1466
- work_dir = Path(tmp) / "work"
1467
- data_root = Path(tmp) / "data"
1468
- cache_root = Path(tmp) / "cache"
1469
-
1470
- # sf org display payload reports v66 — this is the shape real
1471
- # orgs return today (my-org-alias, my-perf-org-alias).
1472
- org_display_payload = {
1473
- "status": 0,
1474
- "result": {
1475
- "instanceUrl": "https://example.my.salesforce.com",
1476
- "accessToken": "00Dxx0000000000!AQ_fake_token_value",
1477
- "id": "00Dxx0000000000AAA",
1478
- "apiVersion": "66.0",
1479
- },
1480
- }
1481
-
1482
- # Capture api_version passed to each fetcher via mock.call_args.
1483
- wave_a_patches = [
1484
- mock.patch.object(main, "fetch_planner_definition",
1485
- return_value=fx.CLASSIC_PLANNER),
1486
- mock.patch.object(main, "fetch_plugins_by_planner",
1487
- return_value=fx.CLASSIC_PLUGINS),
1488
- mock.patch.object(main, "fetch_planner_bundle_functions",
1489
- return_value=fx.CLASSIC_BUNDLE_FN_JOIN),
1490
- mock.patch.object(main, "fetch_functions_by_plugins",
1491
- return_value=fx.CLASSIC_FUNCTIONS),
1492
- mock.patch.object(main, "fetch_plugin_instructions",
1493
- return_value=fx.CLASSIC_INSTRUCTIONS),
1494
- mock.patch.object(main, "fetch_plugin_functions",
1495
- return_value=fx.CLASSIC_PLUGIN_FUNCTIONS),
1496
- mock.patch.object(main, "fetch_planner_attrs",
1497
- return_value=fx.CLASSIC_ATTRS),
1498
- ]
1499
- wave_b_patches = [
1500
- mock.patch.object(main, "fetch_apex_bodies_by_names",
1501
- return_value=fx.CLASSIC_APEX_ROWS),
1502
- mock.patch.object(main, "fetch_apex_bodies_by_ids",
1503
- return_value=[]),
1504
- mock.patch.object(main, "fetch_flow_definition_ids_by_names",
1505
- return_value=fx.CLASSIC_FLOW_DEFS),
1506
- mock.patch.object(main, "fetch_flow_definition_by_ids",
1507
- return_value=[]),
1508
- mock.patch.object(
1509
- main, "fetch_flow_metadata",
1510
- side_effect=lambda vid, *a, **kw: fx.CLASSIC_FLOW_METADATA.get(vid),
1511
- ),
1512
- ]
1513
- patches = [
1514
- mock.patch.object(main, "run_sf", return_value=org_display_payload),
1515
- mock.patch.object(main, "probe_channels",
1516
- return_value=fx.probe_ok_payload()),
1517
- *_mock_bot_resolution(),
1518
- *wave_a_patches,
1519
- *wave_b_patches,
1520
- mock.patch.object(main, "build_agent_data_dir",
1521
- side_effect=lambda o, a, v: data_root / o / f"{a}__{v}"),
1522
- mock.patch.object(main, "build_agent_cache_dir",
1523
- side_effect=lambda o, a, v: cache_root / o / f"{a}__{v}"),
1524
- ]
1525
- _apply_all(patches)
1526
- try:
1527
- rc = main.main(_args(work_dir))
1528
- # Snapshot call lists BEFORE `p.stop()` restores the
1529
- # originals — otherwise `main.fetch_*` drops back to the
1530
- # real function with no `.call_args_list`.
1531
- fetcher_call_lists = {
1532
- name: getattr(main, name).call_args_list
1533
- for name in (
1534
- "fetch_planner_definition",
1535
- "fetch_plugins_by_planner",
1536
- "fetch_planner_bundle_functions",
1537
- "fetch_functions_by_plugins",
1538
- "fetch_plugin_instructions",
1539
- "fetch_plugin_functions",
1540
- "fetch_planner_attrs",
1541
- "fetch_apex_bodies_by_names",
1542
- "fetch_flow_definition_ids_by_names",
1543
- "fetch_flow_metadata",
1544
- "fetch_bot_versions",
1545
- "fetch_bot_definition_details",
1546
- )
1547
- }
1548
- finally:
1549
- for p in patches:
1550
- p.stop()
1551
-
1552
- self.assertEqual(rc, 0)
1553
-
1554
- # Every Wave-A + Wave-B fetcher received `api_version="v66.0"`.
1555
- # We inspect call_args.kwargs rather than positional args — the
1556
- # kwarg is keyword-only by design.
1557
- expected = "v66.0"
1558
- for name, calls in fetcher_call_lists.items():
1559
- calls_with_version = [
1560
- c for c in calls
1561
- if c.kwargs.get("api_version") == expected
1562
- ]
1563
- self.assertTrue(
1564
- calls_with_version,
1565
- f"{name}: no call observed with api_version={expected!r}. "
1566
- f"All calls: {calls}",
1567
- )
1568
-
1569
-
1570
- class UncaughtExceptionToResultBlockTests(unittest.TestCase):
1571
- """the skill contract says every exit path emits a RESULT
1572
- block. Before the fix, an uncaught exception in the pipeline (e.g.
1573
- the HTTP 405 from , or any future bug) propagated to the
1574
- process boundary — users saw a Python traceback on stderr and the
1575
- wrapper skill never got `.emit_ctx.json`. `main()` now wraps
1576
- `_run_pipeline` in `try/except Exception` and funnels failures
1577
- through `_emit_fail(..., "RETRIEVE_FAILED", "uncaught-exception: ...")`.
1578
- """
1579
-
1580
- def test_uncaught_exception_surfaces_as_retrieve_failed(self):
1581
- with tempfile.TemporaryDirectory() as tmp:
1582
- work_dir = Path(tmp) / "work"
1583
-
1584
- # Patch `_run_pipeline` to raise an arbitrary non-HTTP bug
1585
- # shape — proves the wrapper catches broad `Exception`, not
1586
- # just the specific HTTPError from .
1587
- with mock.patch.object(
1588
- main, "_run_pipeline",
1589
- side_effect=RuntimeError("unexpected defect in phase 6"),
1590
- ):
1591
- rc = main.main(_args(work_dir))
1592
-
1593
- # Exit code MUST be non-zero (failure signal) but controlled —
1594
- # no Python traceback on stderr.
1595
- self.assertEqual(rc, 1)
1596
-
1597
- # `.emit_ctx.json` MUST exist — the skill contract.
1598
- ctx_path = work_dir / ".emit_ctx.json"
1599
- self.assertTrue(ctx_path.is_file(),
1600
- "uncaught exception must still write .emit_ctx.json")
1601
- ctx = _read_ctx(work_dir)
1602
- self.assertEqual(ctx["status"], "RETRIEVE_FAILED")
1603
- self.assertIn("uncaught-exception", ctx["error_detail"])
1604
- self.assertIn("RuntimeError", ctx["error_detail"])
1605
- self.assertIn("unexpected defect in phase 6", ctx["error_detail"])
1606
-
1607
- def test_uncaught_exception_redacts_bearer_tokens(self):
1608
- """the redacted error_detail must not leak tokens even if
1609
- the exception message happens to carry one."""
1610
- with tempfile.TemporaryDirectory() as tmp:
1611
- work_dir = Path(tmp) / "work"
1612
-
1613
- leaky = RuntimeError(
1614
- "downstream failed: Authorization: Bearer TESTONLY_LEAKY_TOKEN"
1615
- )
1616
- with mock.patch.object(main, "_run_pipeline", side_effect=leaky):
1617
- rc = main.main(_args(work_dir))
1618
-
1619
- self.assertEqual(rc, 1)
1620
- ctx = _read_ctx(work_dir)
1621
- self.assertEqual(ctx["status"], "RETRIEVE_FAILED")
1622
- # Token must NOT appear.
1623
- self.assertNotIn("TESTONLY_LEAKY_TOKEN", ctx["error_detail"])
1624
- # Redaction sentinel must appear — proof the scrub ran.
1625
- self.assertIn("<redacted>", ctx["error_detail"])
1626
-
1627
- def test_systemexit_still_propagates(self):
1628
- """argparse's --help path raises SystemExit. That MUST propagate
1629
- unchanged — catching it would silently swallow `--help` + any
1630
- other intentional early exit. The wrapper catches `Exception`,
1631
- not `BaseException`, so SystemExit is unaffected."""
1632
- with tempfile.TemporaryDirectory() as tmp:
1633
- work_dir = Path(tmp) / "work"
1634
-
1635
- with mock.patch.object(main, "_run_pipeline",
1636
- side_effect=SystemExit(2)):
1637
- with self.assertRaises(SystemExit) as ctx:
1638
- main.main(_args(work_dir))
1639
- self.assertEqual(ctx.exception.code, 2)
1640
-
1641
-
1642
- class NormalizeFlowIdTargetsTests(unittest.TestCase):
1643
- """classic bots occasionally store NGA-style
1644
- 300Uv-prefix FlowDefinition IDs or 301-prefix Flow version IDs as
1645
- InvocationTarget. After Wave B resolves them we rewrite bundle_parsed
1646
- in place so parse_wave sees DeveloperNames and the pending/visited
1647
- diff collapses to zero for legitimate targets."""
1648
-
1649
- def test_rewrites_flowdefinition_id_to_developer_name(self):
1650
- bundle = {
1651
- "topics": [{
1652
- "name": "T",
1653
- "actions": [{
1654
- "name": "A",
1655
- "invocationTarget": "300UvXXXXXXXXXXXX",
1656
- "invocationTargetType": "flow",
1657
- }],
1658
- }],
1659
- "plannerActions": [],
1660
- }
1661
- flow_def_rows = [{
1662
- "Id": "300UvXXXXXXXXXXXX",
1663
- "DeveloperName": "MyFlowName",
1664
- "ActiveVersionId": "301VfYYYYYYYYYYYY",
1665
- }]
1666
- main._normalize_flow_id_targets(bundle, flow_def_rows)
1667
- action = bundle["topics"][0]["actions"][0]
1668
- self.assertEqual(action["invocationTarget"], "MyFlowName")
1669
- self.assertEqual(action["_original_invocation_target_id"],
1670
- "300UvXXXXXXXXXXXX")
1671
-
1672
- def test_rewrites_flow_version_id_via_active_version_map(self):
1673
- """301-prefix IDs should also resolve — via the ActiveVersionId
1674
- side of the bi-directional map."""
1675
- bundle = {
1676
- "topics": [{
1677
- "actions": [{
1678
- "invocationTarget": "301VfYYYYYYYYYYYY",
1679
- "invocationTargetType": "flow",
1680
- }],
1681
- }],
1682
- "plannerActions": [],
1683
- }
1684
- flow_def_rows = [{
1685
- "Id": "300UvXXXXXXXXXXXX",
1686
- "DeveloperName": "MyFlowName",
1687
- "ActiveVersionId": "301VfYYYYYYYYYYYY",
1688
- }]
1689
- main._normalize_flow_id_targets(bundle, flow_def_rows)
1690
- self.assertEqual(
1691
- bundle["topics"][0]["actions"][0]["invocationTarget"],
1692
- "MyFlowName",
1693
- )
1694
-
1695
- def test_preserves_classic_developer_name_targets(self):
1696
- """Classic DeveloperName targets must pass through untouched —
1697
- they have nothing to resolve AND shouldn't pick up the sentinel
1698
- _original_invocation_target_id field."""
1699
- bundle = {
1700
- "topics": [{
1701
- "actions": [{
1702
- "invocationTarget": "AGNT_Case_Create",
1703
- "invocationTargetType": "flow",
1704
- }],
1705
- }],
1706
- "plannerActions": [],
1707
- }
1708
- flow_def_rows = [{
1709
- "Id": "300UvXXXXXXXXXXXX",
1710
- "DeveloperName": "AGNT_Case_Create",
1711
- "ActiveVersionId": "301VfYYYYYYYYYYYY",
1712
- }]
1713
- main._normalize_flow_id_targets(bundle, flow_def_rows)
1714
- action = bundle["topics"][0]["actions"][0]
1715
- self.assertEqual(action["invocationTarget"], "AGNT_Case_Create")
1716
- self.assertNotIn("_original_invocation_target_id", action)
1717
-
1718
- def test_unmatched_id_stays_as_is(self):
1719
- """An ID that doesn't appear in flow_def_rows (Flow not queryable
1720
- / managed package invisible) stays unchanged — that's how it
1721
- correctly surfaces in _pending_fetches instead of silently
1722
- discarding."""
1723
- bundle = {
1724
- "topics": [{
1725
- "actions": [{
1726
- "invocationTarget": "300UvZZZZZZZZZZZZ",
1727
- "invocationTargetType": "flow",
1728
- }],
1729
- }],
1730
- "plannerActions": [],
1731
- }
1732
- main._normalize_flow_id_targets(bundle, [{
1733
- "Id": "300UvXXXXXXXXXXXX",
1734
- "DeveloperName": "DifferentFlow",
1735
- "ActiveVersionId": "301VfYYYYYYYYYYYY",
1736
- }])
1737
- self.assertEqual(
1738
- bundle["topics"][0]["actions"][0]["invocationTarget"],
1739
- "300UvZZZZZZZZZZZZ",
1740
- )
1741
-
1742
- def test_apex_target_with_300_prefix_not_rewritten(self):
1743
- """Only invocationTargetType=='flow' is rewritten. A target that
1744
- happens to match a flow id but is declared as apex stays put —
1745
- it's a caller-error we surface, not one we silently rewrite."""
1746
- bundle = {
1747
- "topics": [{
1748
- "actions": [{
1749
- "invocationTarget": "300UvXXXXXXXXXXXX",
1750
- "invocationTargetType": "apex", # wrong type
1751
- }],
1752
- }],
1753
- "plannerActions": [],
1754
- }
1755
- flow_def_rows = [{
1756
- "Id": "300UvXXXXXXXXXXXX",
1757
- "DeveloperName": "MyFlow",
1758
- "ActiveVersionId": "301VfYYYYYYYYYYYY",
1759
- }]
1760
- main._normalize_flow_id_targets(bundle, flow_def_rows)
1761
- self.assertEqual(
1762
- bundle["topics"][0]["actions"][0]["invocationTarget"],
1763
- "300UvXXXXXXXXXXXX",
1764
- )
1765
-
1766
- def test_empty_inputs_noop(self):
1767
- """Empty flow_def_rows → immediate return, no mutation, no crash
1768
- on missing 'topics' / 'plannerActions' keys."""
1769
- bundle = {}
1770
- main._normalize_flow_id_targets(bundle, [])
1771
- self.assertEqual(bundle, {})
1772
-
1773
- bundle2 = {
1774
- "topics": [{"actions": [{
1775
- "invocationTarget": "300Uv", "invocationTargetType": "flow",
1776
- }]}],
1777
- "plannerActions": [],
1778
- }
1779
- main._normalize_flow_id_targets(bundle2, [])
1780
- # Untouched — no lookup map to rewrite against.
1781
- self.assertEqual(
1782
- bundle2["topics"][0]["actions"][0]["invocationTarget"], "300Uv",
1783
- )
1784
-
1785
- def test_rewrites_both_topics_and_planner_actions(self):
1786
- """Fix must cover both the per-topic actions path AND the
1787
- bundle-scope plannerActions path."""
1788
- bundle = {
1789
- "topics": [{
1790
- "actions": [{
1791
- "invocationTarget": "300UvAAAA",
1792
- "invocationTargetType": "flow",
1793
- }],
1794
- }],
1795
- "plannerActions": [{
1796
- "invocationTarget": "300UvBBBB",
1797
- "invocationTargetType": "flow",
1798
- }],
1799
- }
1800
- flow_def_rows = [
1801
- {"Id": "300UvAAAA", "DeveloperName": "TopicFlow",
1802
- "ActiveVersionId": "301AAAA"},
1803
- {"Id": "300UvBBBB", "DeveloperName": "BundleFlow",
1804
- "ActiveVersionId": "301BBBB"},
1805
- ]
1806
- main._normalize_flow_id_targets(bundle, flow_def_rows)
1807
- self.assertEqual(
1808
- bundle["topics"][0]["actions"][0]["invocationTarget"], "TopicFlow",
1809
- )
1810
- self.assertEqual(
1811
- bundle["plannerActions"][0]["invocationTarget"], "BundleFlow",
1812
- )
1813
-
1814
- def test_none_invocation_target_type_ignored_safely(self):
1815
- """Defensive: invocationTargetType missing → treat as 'not a
1816
- flow', skip. No crash."""
1817
- bundle = {
1818
- "topics": [{"actions": [{
1819
- "invocationTarget": "300UvAAAA",
1820
- "invocationTargetType": None,
1821
- }]}],
1822
- "plannerActions": [],
1823
- }
1824
- main._normalize_flow_id_targets(bundle, [
1825
- {"Id": "300UvAAAA", "DeveloperName": "X", "ActiveVersionId": "301"}
1826
- ])
1827
- self.assertEqual(
1828
- bundle["topics"][0]["actions"][0]["invocationTarget"], "300UvAAAA",
1829
- )
1830
-
1831
-
1832
- class CollectWaveBTargetsStandardActionTests(unittest.TestCase):
1833
- """`_route` in `_collect_wave_b_targets` must
1834
- short-circuit on declared-only target types (standardInvocableAction,
1835
- generatePromptResponse, genai*, prompt*) BEFORE calling
1836
- resolve_or_unresolved — otherwise it pollutes `_unresolved` with
1837
- spurious "invalid-id-format" entries for perfectly valid identifiers
1838
- that simply aren't Salesforce Ids."""
1839
-
1840
- def test_standard_action_not_routed_through_id_resolver(self):
1841
- """`streamKnowledgeSearch` is a built-in standard action — not
1842
- an Id. It should not end up in apex_ids, flow_ids, apex_names,
1843
- or flow_names AND it should NOT appear in the `_unresolved`
1844
- list that resolve_or_unresolved populates on non-Id inputs.
1845
- """
1846
- bundle = {
1847
- "topics": [{
1848
- "name": "T",
1849
- "actions": [{
1850
- "name": "A",
1851
- "invocationTarget": "streamKnowledgeSearch",
1852
- "invocationTargetType": "standardInvocableAction",
1853
- }],
1854
- }],
1855
- "plannerActions": [],
1856
- }
1857
- result = main._collect_wave_b_targets(bundle)
1858
- self.assertEqual(result["apex_names"], [])
1859
- self.assertEqual(result["apex_ids"], [])
1860
- self.assertEqual(result["flow_names"], [])
1861
- self.assertEqual(result["flow_ids"], [])
1862
- self.assertEqual(
1863
- result["_unresolved"], [],
1864
- "standardInvocableAction must not pollute _unresolved with "
1865
- "invalid-id-format entries",
1866
- )
1867
-
1868
- def test_generate_prompt_response_short_circuits(self):
1869
- """`generatePromptResponse` targets are prompt-template names;
1870
- not routed to Apex/Flow fetchers (Batch 1 is body-only for
1871
- Apex+Flow; prompts flow through the retrieve path)."""
1872
- bundle = {
1873
- "topics": [{
1874
- "name": "T",
1875
- "actions": [{
1876
- "invocationTarget": "MyPromptTemplate",
1877
- "invocationTargetType": "generatePromptResponse",
1878
- }],
1879
- }],
1880
- "plannerActions": [],
1881
- }
1882
- result = main._collect_wave_b_targets(bundle)
1883
- self.assertEqual(result["apex_names"], [])
1884
- self.assertEqual(result["flow_names"], [])
1885
- self.assertEqual(result["_unresolved"], [])
1886
-
1887
- def test_flow_and_apex_still_route_correctly(self):
1888
- """Positive control — the short-circuit must not break flow/apex
1889
- routing. A mix of classic DeveloperNames + NGA IDs should land in
1890
- the right buckets, and standard actions should pass through
1891
- without polluting anything."""
1892
- bundle = {
1893
- "topics": [{
1894
- "name": "T",
1895
- "actions": [
1896
- # Classic flow by DeveloperName
1897
- {"invocationTarget": "MyFlow",
1898
- "invocationTargetType": "flow"},
1899
- # Classic apex by name
1900
- {"invocationTarget": "MyApex",
1901
- "invocationTargetType": "apex"},
1902
- # Standard action (new short-circuit path)
1903
- {"invocationTarget": "streamKnowledgeSearch",
1904
- "invocationTargetType": "standardInvocableAction"},
1905
- # NGA apex by Id
1906
- {"invocationTarget": "01p1N000005SsDNQA0",
1907
- "invocationTargetType": "apex"},
1908
- ],
1909
- }],
1910
- "plannerActions": [],
1911
- }
1912
- result = main._collect_wave_b_targets(bundle)
1913
- self.assertIn("MyFlow", result["flow_names"])
1914
- self.assertIn("MyApex", result["apex_names"])
1915
- self.assertIn("01p1N000005SsDNQA0", result["apex_ids"])
1916
- self.assertEqual(result["_unresolved"], [])
1917
-
1918
- def test_unknown_type_silently_skipped(self):
1919
- """An unrecognized invocationTargetType falls through all the
1920
- known-type branches and is silently skipped. parse_wave tags the
1921
- node as UNKNOWN in the tree (via `_kind_counts`), so the signal
1922
- is visible without polluting _unresolved."""
1923
- bundle = {
1924
- "topics": [{
1925
- "name": "T",
1926
- "actions": [{
1927
- "invocationTarget": "SomeThing",
1928
- "invocationTargetType": "unheardOfType",
1929
- }],
1930
- }],
1931
- "plannerActions": [],
1932
- }
1933
- result = main._collect_wave_b_targets(bundle)
1934
- self.assertEqual(result["apex_names"], [])
1935
- self.assertEqual(result["flow_names"], [])
1936
- self.assertEqual(
1937
- result["_unresolved"], [],
1938
- "Unknown invocationTargetType shouldn't reach the ID router, "
1939
- "so _unresolved stays clean.",
1940
- )
1941
-
1942
- def test_classic_flow_name_not_routed_through_id_resolver(self):
1943
- """classic bots store plain DeveloperNames
1944
- like `MyFlow` — not Salesforce Ids. The router must route these
1945
- directly to flow_names via invocationTargetType, NOT through
1946
- resolve_or_unresolved (which would reject them as invalid-id-
1947
- format and pollute _unresolved)."""
1948
- bundle = {
1949
- "topics": [{
1950
- "actions": [
1951
- {"invocationTarget": "MyFlow",
1952
- "invocationTargetType": "flow"},
1953
- {"invocationTarget": "AGNT_Foo",
1954
- "invocationTargetType": "apex"},
1955
- ],
1956
- }],
1957
- "plannerActions": [],
1958
- }
1959
- result = main._collect_wave_b_targets(bundle)
1960
- self.assertIn("MyFlow", result["flow_names"])
1961
- self.assertIn("AGNT_Foo", result["apex_names"])
1962
- self.assertEqual(
1963
- result["_unresolved"], [],
1964
- "Classic DeveloperNames shouldn't be sent through the ID "
1965
- "resolver at all — they're not Ids.",
1966
- )
1967
-
1968
-
1969
- class NormalizePromptTemplateIdTargetsTests(unittest.TestCase):
1970
- """Bug 1 fix (2026-05-05): classic bots occasionally store 0hf-prefix
1971
- GenAiPromptTemplate IDs as `GenAiFunctionDefinition.InvocationTarget`.
1972
- After Wave B resolves them via `list_prompt_template_metadata`
1973
- (GenAiPromptTemplate is NOT SOQL-queryable — Metadata API only) we
1974
- rewrite bundle_parsed in place so Wave B's retrieve uses the
1975
- DeveloperName Metadata API expects."""
1976
-
1977
- def test_rewrites_prompt_template_id_to_developer_name(self):
1978
- bundle = {
1979
- "topics": [{
1980
- "actions": [{
1981
- "invocationTarget": "0hfUv0000021mCjIAI",
1982
- "invocationTargetType": "GenAiPromptTemplate",
1983
- }],
1984
- }],
1985
- "plannerActions": [],
1986
- }
1987
- rows = [{"Id": "0hfUv0000021mCjIAI", "DeveloperName": "My_Prompt"}]
1988
- main._normalize_prompt_template_id_targets(bundle, rows)
1989
- action = bundle["topics"][0]["actions"][0]
1990
- self.assertEqual(action["invocationTarget"], "My_Prompt")
1991
- self.assertEqual(
1992
- action["_original_invocation_target_id"], "0hfUv0000021mCjIAI"
1993
- )
1994
-
1995
- def test_preserves_classic_developer_name_targets(self):
1996
- """Classic DeveloperName targets pass through untouched — the
1997
- rewrite is only for Id-shaped targets that appeared in the lookup."""
1998
- bundle = {
1999
- "topics": [{
2000
- "actions": [{
2001
- "invocationTarget": "Existing_Prompt_Name",
2002
- "invocationTargetType": "GenAiPromptTemplate",
2003
- }],
2004
- }],
2005
- "plannerActions": [],
2006
- }
2007
- # Lookup covers a different Id entirely — the DeveloperName target
2008
- # isn't a key in the map so it's not rewritten.
2009
- rows = [{"Id": "0hfUv0000021Other", "DeveloperName": "Other_Prompt"}]
2010
- main._normalize_prompt_template_id_targets(bundle, rows)
2011
- action = bundle["topics"][0]["actions"][0]
2012
- self.assertEqual(action["invocationTarget"], "Existing_Prompt_Name")
2013
- self.assertNotIn("_original_invocation_target_id", action)
2014
-
2015
- def test_unmatched_id_stays_as_is(self):
2016
- """Id not present in the lookup (e.g. Tooling returned empty
2017
- because GenAiPromptTemplate isn't exposed on this org) stays
2018
- as-is so it correctly surfaces in _pending_fetches."""
2019
- bundle = {
2020
- "topics": [{
2021
- "actions": [{
2022
- "invocationTarget": "0hfUv00000xxxxxYYY",
2023
- "invocationTargetType": "GenAiPromptTemplate",
2024
- }],
2025
- }],
2026
- "plannerActions": [],
2027
- }
2028
- main._normalize_prompt_template_id_targets(bundle, [])
2029
- action = bundle["topics"][0]["actions"][0]
2030
- self.assertEqual(action["invocationTarget"], "0hfUv00000xxxxxYYY")
2031
- self.assertNotIn("_original_invocation_target_id", action)
2032
-
2033
-
2034
- class NormalizeApexIdTargetsTests(unittest.TestCase):
2035
- """Gap B fix (2026-05-05): classic bots occasionally store 01p-prefix
2036
- ApexClass Ids as `GenAiFunctionDefinition.InvocationTarget` (live-verified
2037
- on my-org-alias: 01p000000000000AAA -> MyController).
2038
- After Wave B resolves them via `fetch_apex_bodies_by_ids` we rewrite
2039
- bundle_parsed in place so the tree renders the ApexClass Name instead
2040
- of the raw Id."""
2041
-
2042
- def test_rewrites_apex_id_to_class_name(self):
2043
- bundle = {
2044
- "topics": [{
2045
- "actions": [{
2046
- "invocationTarget": "01p000000000000AAA",
2047
- "invocationTargetType": "apex",
2048
- }],
2049
- }],
2050
- "plannerActions": [],
2051
- }
2052
- rows = [{"Id": "01p000000000000AAA", "Name": "MyController"}]
2053
- main._normalize_apex_id_targets(bundle, rows)
2054
- action = bundle["topics"][0]["actions"][0]
2055
- self.assertEqual(action["invocationTarget"], "MyController")
2056
- self.assertEqual(
2057
- action["_original_invocation_target_id"], "01p000000000000AAA"
2058
- )
2059
-
2060
- def test_non_apex_ttype_left_unchanged(self):
2061
- """Same Id but a non-apex ttype — the ttype gate must block the
2062
- rewrite so a Flow action whose target happens to collide with an
2063
- ApexClass Id isn't miscaught."""
2064
- bundle = {
2065
- "topics": [{
2066
- "actions": [{
2067
- "invocationTarget": "01p000000000000AAA",
2068
- "invocationTargetType": "flow",
2069
- }],
2070
- }],
2071
- "plannerActions": [],
2072
- }
2073
- rows = [{"Id": "01p000000000000AAA", "Name": "MyController"}]
2074
- main._normalize_apex_id_targets(bundle, rows)
2075
- action = bundle["topics"][0]["actions"][0]
2076
- self.assertEqual(action["invocationTarget"], "01p000000000000AAA")
2077
- self.assertNotIn("_original_invocation_target_id", action)
2078
-
2079
- def test_unmatched_id_stays_as_is(self):
2080
- """Id not present in the lookup (e.g. by-Id fetch failed or the
2081
- class was deleted) stays as-is so it correctly surfaces in
2082
- _pending_fetches."""
2083
- bundle = {
2084
- "topics": [{
2085
- "actions": [{
2086
- "invocationTarget": "01pFAKEIDFAKEIDAAA",
2087
- "invocationTargetType": "apex",
2088
- }],
2089
- }],
2090
- "plannerActions": [],
2091
- }
2092
- main._normalize_apex_id_targets(bundle, [])
2093
- action = bundle["topics"][0]["actions"][0]
2094
- self.assertEqual(action["invocationTarget"], "01pFAKEIDFAKEIDAAA")
2095
- self.assertNotIn("_original_invocation_target_id", action)
2096
-
2097
- def test_preserves_classic_developer_name_targets(self):
2098
- """Classic Name targets pass through untouched — the rewrite is
2099
- only for Id-shaped targets (01p-prefix) that appeared in the lookup."""
2100
- bundle = {
2101
- "topics": [{
2102
- "actions": [{
2103
- "invocationTarget": "MyApexClass",
2104
- "invocationTargetType": "apex",
2105
- }],
2106
- }],
2107
- "plannerActions": [],
2108
- }
2109
- # Lookup covers a different Id entirely — the Name target isn't
2110
- # Id-shaped and doesn't hit the prefix gate.
2111
- rows = [{"Id": "01p000000000000AAA", "Name": "MyController"}]
2112
- main._normalize_apex_id_targets(bundle, rows)
2113
- action = bundle["topics"][0]["actions"][0]
2114
- self.assertEqual(action["invocationTarget"], "MyApexClass")
2115
- self.assertNotIn("_original_invocation_target_id", action)
2116
-
2117
-
2118
- class CollectWaveBTargetsPromptTemplateIdTests(unittest.TestCase):
2119
- """Bug 1 fix (2026-05-05): 0hf-prefix prompt template Ids are routed
2120
- to a dedicated `prompt_template_ids` bucket so post-Wave-B resolution
2121
- can rewrite them; DeveloperName targets still short-circuit as before."""
2122
-
2123
- def test_prompt_template_id_routes_to_id_bucket(self):
2124
- bundle = {
2125
- "topics": [],
2126
- "plannerActions": [{
2127
- "invocationTarget": "0hfUv0000021mCjIAI",
2128
- "invocationTargetType": "GenAiPromptTemplate",
2129
- }],
2130
- }
2131
- result = main._collect_wave_b_targets(bundle)
2132
- self.assertEqual(
2133
- result.get("prompt_template_ids"), ["0hfUv0000021mCjIAI"]
2134
- )
2135
- # DeveloperName bucket stays empty — the Id is routed to the Id
2136
- # bucket and the short-circuit returns BEFORE the DeveloperName
2137
- # branch would have run.
2138
- self.assertEqual(result.get("_unresolved"), [])
2139
-
2140
- def test_prompt_template_developer_name_does_not_pollute_id_bucket(self):
2141
- bundle = {
2142
- "topics": [],
2143
- "plannerActions": [{
2144
- "invocationTarget": "My_Prompt_Template_Name",
2145
- "invocationTargetType": "GenAiPromptTemplate",
2146
- }],
2147
- }
2148
- result = main._collect_wave_b_targets(bundle)
2149
- self.assertEqual(result.get("prompt_template_ids"), [])
2150
- # DeveloperName-shaped prompt-template targets still short-circuit
2151
- # (parse_wave enqueues them into PROMPT_TEMPLATE pending) — no
2152
- # change from prior behavior, verified via absence from all
2153
- # name/id buckets we'd route through.
2154
- self.assertEqual(result.get("apex_names"), [])
2155
- self.assertEqual(result.get("flow_names"), [])
2156
-
2157
- def test_non_0hf_prefix_ignored(self):
2158
- """Id-shaped target for a prompt-template ttype but WRONG prefix
2159
- (e.g. a Flow Id accidentally typed with prompt ttype) doesn't
2160
- pollute prompt_template_ids — the prefix gate catches it."""
2161
- bundle = {
2162
- "topics": [],
2163
- "plannerActions": [{
2164
- "invocationTarget": "300Uv00000abcdeFGH", # Flow-shaped Id
2165
- "invocationTargetType": "GenAiPromptTemplate",
2166
- }],
2167
- }
2168
- result = main._collect_wave_b_targets(bundle)
2169
- # Not routed anywhere — neither prompt-template Id bucket nor
2170
- # flow buckets (ttype gated). Surfaces nowhere, which is
2171
- # acceptable: classify_action_call downstream will still enqueue
2172
- # the string as-is as a PROMPT_TEMPLATE pending fetch.
2173
- self.assertEqual(result.get("prompt_template_ids"), [])
2174
-
2175
-
2176
- class FetchFlowDefinitionViewByDurableIdsTests(unittest.TestCase):
2177
- """Option B (2026-05-05): `fetch_flow_definition_view_by_durable_ids`
2178
- is the Data-API fallback fetcher for managed-installed flows that
2179
- Tooling's `FlowDefinition` doesn't index.
2180
-
2181
- Contract:
2182
- * Empty input short-circuits to `[]` without firing a SOQL call
2183
- (matches every other list-shaped fetcher in this module).
2184
- * Rows are returned from `data_query` verbatim — projection to
2185
- the `flow_def_rows` shape happens in the caller
2186
- (`fetch_flow_definition_ids_by_names`).
2187
- """
2188
-
2189
- def test_happy_path_returns_rows(self):
2190
- import fetch_soql # type: ignore
2191
- view_row = {
2192
- "DurableId": "SvcCopilotTmpl__VerifyCode",
2193
- "ApiName": "VerifyCode",
2194
- "Label": "Verify Code",
2195
- "NamespacePrefix": "SvcCopilotTmpl",
2196
- "ActiveVersionId": "SvcCopilotTmpl__VerifyCode-1",
2197
- "IsActive": True,
2198
- "ManageableState": "installed",
2199
- "ProcessType": "AutoLaunchedFlow",
2200
- }
2201
- with mock.patch.object(
2202
- fetch_soql, "data_query",
2203
- return_value={"records": [view_row]},
2204
- ) as mock_dq:
2205
- rows = fetch_soql.fetch_flow_definition_view_by_durable_ids(
2206
- ["SvcCopilotTmpl__VerifyCode"],
2207
- lambda: ("url", "tok"),
2208
- api_version="v60.0",
2209
- on_401_refresh=lambda: ("url", "tok"),
2210
- )
2211
- self.assertEqual(rows, [view_row])
2212
- # Exactly one data_query call — the fetcher doesn't accidentally
2213
- # re-fire on the Tooling surface.
2214
- self.assertEqual(mock_dq.call_count, 1)
2215
-
2216
- def test_empty_input_short_circuits(self):
2217
- """Empty durable_ids list returns [] WITHOUT firing a SOQL call
2218
- (matches the module-wide empty-input-short-circuit invariant)."""
2219
- import fetch_soql # type: ignore
2220
- with mock.patch.object(fetch_soql, "data_query") as mock_dq:
2221
- rows = fetch_soql.fetch_flow_definition_view_by_durable_ids(
2222
- [],
2223
- lambda: ("url", "tok"),
2224
- api_version="v60.0",
2225
- on_401_refresh=lambda: ("url", "tok"),
2226
- )
2227
- self.assertEqual(rows, [])
2228
- self.assertEqual(mock_dq.call_count, 0)
2229
-
2230
- def test_multi_row_returns_all(self):
2231
- import fetch_soql # type: ignore
2232
- view_rows = [
2233
- {
2234
- "DurableId": "SvcCopilotTmpl__VerifyCode",
2235
- "ApiName": "VerifyCode",
2236
- "NamespacePrefix": "SvcCopilotTmpl",
2237
- "ActiveVersionId": "SvcCopilotTmpl__VerifyCode-1",
2238
- "ManageableState": "installed",
2239
- },
2240
- {
2241
- "DurableId": "sales_inbound_flows__SendVerifyCode",
2242
- "ApiName": "SendVerifyCode",
2243
- "NamespacePrefix": "sales_inbound_flows",
2244
- "ActiveVersionId": "sales_inbound_flows__SendVerifyCode-2",
2245
- "ManageableState": "installed",
2246
- },
2247
- ]
2248
- with mock.patch.object(
2249
- fetch_soql, "data_query",
2250
- return_value={"records": view_rows},
2251
- ):
2252
- rows = fetch_soql.fetch_flow_definition_view_by_durable_ids(
2253
- [
2254
- "SvcCopilotTmpl__VerifyCode",
2255
- "sales_inbound_flows__SendVerifyCode",
2256
- ],
2257
- lambda: ("url", "tok"),
2258
- api_version="v60.0",
2259
- on_401_refresh=lambda: ("url", "tok"),
2260
- )
2261
- self.assertEqual(len(rows), 2)
2262
- # Membership assertion rather than sort-order — codepoint sort of
2263
- # mixed-case prefixes is fragile; the fetcher returns rows in the
2264
- # order `data_query` supplies them.
2265
- self.assertEqual(
2266
- {r["DurableId"] for r in rows},
2267
- {
2268
- "SvcCopilotTmpl__VerifyCode",
2269
- "sales_inbound_flows__SendVerifyCode",
2270
- },
2271
- )
2272
-
2273
-
2274
- class FlowDefinitionViewFallbackTests(unittest.TestCase):
2275
- """Option B (2026-05-05, updated after managed-bucket retirement):
2276
- `fetch_flow_definition_ids_by_names` fires a SINGLE Tooling
2277
- `FlowDefinition` query (unmanaged-only — the template filters
2278
- `NamespacePrefix IS NULL`). Any input name that query doesn't resolve
2279
- triggers a single follow-up `FlowDefinitionView` (Data API) query.
2280
- Projected view-only rows carry `Id=None`, `ActiveVersionId=None`,
2281
- `_body_available=False`, and `_source="FlowDefinitionView"`.
2282
- """
2283
-
2284
- def test_fallback_fires_on_managed_miss(self):
2285
- """Tooling FlowDefinition returns empty for a `ns__Name` input
2286
- (managed flows aren't indexed on subscriber orgs + the unmanaged
2287
- query filters `NamespacePrefix IS NULL` anyway); FlowDefinitionView
2288
- returns a matching row. Output row carries the view-shaped markers
2289
- and `DeveloperName` = qualified ns__bare."""
2290
- import fetch_soql # type: ignore
2291
- view_row = {
2292
- "DurableId": "SvcCopilotTmpl__VerifyCode",
2293
- "ApiName": "VerifyCode",
2294
- "Label": "Verify Code",
2295
- "NamespacePrefix": "SvcCopilotTmpl",
2296
- "ActiveVersionId": "SvcCopilotTmpl__VerifyCode-1",
2297
- "ManageableState": "installed",
2298
- }
2299
- with mock.patch.object(
2300
- fetch_soql, "tooling_query",
2301
- return_value={"records": []},
2302
- ), mock.patch.object(
2303
- fetch_soql, "data_query",
2304
- return_value={"records": [view_row]},
2305
- ) as mock_dq:
2306
- rows = fetch_soql.fetch_flow_definition_ids_by_names(
2307
- ["SvcCopilotTmpl__VerifyCode"],
2308
- lambda: ("url", "tok"),
2309
- api_version="v60.0",
2310
- on_401_refresh=lambda: ("url", "tok"),
2311
- )
2312
- self.assertEqual(len(rows), 1)
2313
- row = rows[0]
2314
- self.assertIsNone(row["Id"])
2315
- self.assertIsNone(row["ActiveVersionId"])
2316
- self.assertFalse(row["_body_available"])
2317
- self.assertEqual(row["_source"], "FlowDefinitionView")
2318
- self.assertEqual(row["DeveloperName"], "SvcCopilotTmpl__VerifyCode")
2319
- self.assertEqual(row["NamespacePrefix"], "SvcCopilotTmpl")
2320
- self.assertEqual(row["_bare_developer_name"], "VerifyCode")
2321
- self.assertEqual(mock_dq.call_count, 1)
2322
-
2323
- def test_fallback_skipped_when_tooling_resolves_everything(self):
2324
- """All input names resolved by Tooling → FlowDefinitionView is
2325
- never queried. Guards against unnecessary Data-API calls on the
2326
- 99% of runs where every referenced flow is unmanaged or locally
2327
- installed."""
2328
- import fetch_soql # type: ignore
2329
- real_row = {
2330
- "Id": "300Uv000000Real",
2331
- "DeveloperName": "MyFlow",
2332
- "NamespacePrefix": None,
2333
- "ActiveVersionId": "301Vf000000Real",
2334
- }
2335
- with mock.patch.object(
2336
- fetch_soql, "tooling_query",
2337
- return_value={"records": [real_row]},
2338
- ), mock.patch.object(fetch_soql, "data_query") as mock_dq:
2339
- rows = fetch_soql.fetch_flow_definition_ids_by_names(
2340
- ["MyFlow"],
2341
- lambda: ("url", "tok"),
2342
- api_version="v60.0",
2343
- on_401_refresh=lambda: ("url", "tok"),
2344
- )
2345
- self.assertEqual(len(rows), 1)
2346
- self.assertEqual(rows[0]["_source"], "FlowDefinition")
2347
- self.assertTrue(rows[0]["_body_available"])
2348
- self.assertEqual(mock_dq.call_count, 0)
2349
-
2350
- def test_mixed_resolution_paths(self):
2351
- """Three input names, three distinct fates:
2352
- 1. `ExistingFlow` — unmanaged, resolved by Tooling.
2353
- 2. `SvcCopilotTmpl__VerifyCode` — managed miss on Tooling,
2354
- resolved by FlowDefinitionView.
2355
- 3. `ghost_ns__GhostFlow` — managed miss on BOTH surfaces.
2356
-
2357
- Expected: 2 rows total (1 real + 1 view-only), the ghost flow
2358
- absent from the result set. FlowDefinitionView queried exactly
2359
- once with both unresolved names in the IN-list.
2360
- """
2361
- import fetch_soql # type: ignore
2362
-
2363
- real_row = {
2364
- "Id": "300Uv000000Real",
2365
- "DeveloperName": "ExistingFlow",
2366
- "NamespacePrefix": None,
2367
- "ActiveVersionId": "301Vf000000Real",
2368
- }
2369
- view_row = {
2370
- "DurableId": "SvcCopilotTmpl__VerifyCode",
2371
- "ApiName": "VerifyCode",
2372
- "NamespacePrefix": "SvcCopilotTmpl",
2373
- "ActiveVersionId": "SvcCopilotTmpl__VerifyCode-1",
2374
- "ManageableState": "installed",
2375
- }
2376
-
2377
- # Tooling is called exactly once — the unmanaged query (template
2378
- # filters NamespacePrefix IS NULL). It matches only ExistingFlow;
2379
- # the two managed-qualified names return no rows from that
2380
- # surface and fall through to the view fallback.
2381
- with mock.patch.object(
2382
- fetch_soql, "tooling_query",
2383
- return_value={"records": [real_row]},
2384
- ) as mock_tq, mock.patch.object(
2385
- fetch_soql, "data_query",
2386
- return_value={"records": [view_row]},
2387
- ) as mock_dq:
2388
- rows = fetch_soql.fetch_flow_definition_ids_by_names(
2389
- [
2390
- "ExistingFlow",
2391
- "SvcCopilotTmpl__VerifyCode",
2392
- "ghost_ns__GhostFlow",
2393
- ],
2394
- lambda: ("url", "tok"),
2395
- api_version="v60.0",
2396
- on_401_refresh=lambda: ("url", "tok"),
2397
- )
2398
- self.assertEqual(len(rows), 2)
2399
- # Tooling queried exactly once for the full input (no bucketing).
2400
- self.assertEqual(mock_tq.call_count, 1)
2401
- # View fallback queried exactly once — no per-name fanout.
2402
- self.assertEqual(mock_dq.call_count, 1)
2403
-
2404
- by_name = {r["DeveloperName"]: r for r in rows}
2405
- # Real Tooling row — source marker explicit.
2406
- self.assertEqual(by_name["ExistingFlow"]["Id"], "300Uv000000Real")
2407
- self.assertEqual(by_name["ExistingFlow"]["_source"], "FlowDefinition")
2408
- self.assertTrue(by_name["ExistingFlow"]["_body_available"])
2409
- # View-only row — no Id, no active version, marked unavailable.
2410
- view_result = by_name["SvcCopilotTmpl__VerifyCode"]
2411
- self.assertIsNone(view_result["Id"])
2412
- self.assertIsNone(view_result["ActiveVersionId"])
2413
- self.assertFalse(view_result["_body_available"])
2414
- self.assertEqual(view_result["_source"], "FlowDefinitionView")
2415
- # Ghost flow absent.
2416
- self.assertNotIn("ghost_ns__GhostFlow", by_name)
2417
-
2418
-
2419
- class FetchPlannerDefinitionChainTests(unittest.TestCase):
2420
- """2026-05-05: `fetch_planner_definition(agent, version)` performs a
2421
- chain-LIKE lookup against GenAiPlannerDefinition. The accretive
2422
- naming invariant (v1=`<Agent>`, v2=`<Agent>_v2`, v3=
2423
- `<Agent>_v2_v3`, ...) means the correct planner always matches
2424
- `<Agent>%\\_vN` for vN>=2 and `<Agent>` exactly for v1. On multi-row
2425
- matches the resolver picks the row with the shortest DeveloperName.
2426
- """
2427
-
2428
- def _stub_tooling(self, records):
2429
- """Patch `fetch_soql.tooling_query` to return a fixed record list."""
2430
- import fetch_soql # type: ignore
2431
- return mock.patch.object(
2432
- fetch_soql, "tooling_query",
2433
- return_value={"records": records},
2434
- )
2435
-
2436
- def test_v1_exact_match(self):
2437
- import fetch_soql # type: ignore
2438
- with self._stub_tooling([
2439
- {"Id": "1VxVF000V1", "DeveloperName": "Inbound_Sales_Agent"},
2440
- ]):
2441
- row = fetch_soql.fetch_planner_definition(
2442
- "Inbound_Sales_Agent", None,
2443
- lambda: ("url", "tok"),
2444
- api_version="v66.0",
2445
- on_401_refresh=lambda: ("url", "tok"),
2446
- )
2447
- self.assertIsNotNone(row)
2448
- self.assertEqual(row["DeveloperName"], "Inbound_Sales_Agent")
2449
-
2450
- def test_v1_explicit_string(self):
2451
- import fetch_soql # type: ignore
2452
- with self._stub_tooling([
2453
- {"Id": "1VxVF000V1", "DeveloperName": "Inbound_Sales_Agent"},
2454
- ]):
2455
- row = fetch_soql.fetch_planner_definition(
2456
- "Inbound_Sales_Agent", "v1",
2457
- lambda: ("url", "tok"),
2458
- api_version="v66.0",
2459
- on_401_refresh=lambda: ("url", "tok"),
2460
- )
2461
- self.assertEqual(row["DeveloperName"], "Inbound_Sales_Agent")
2462
-
2463
- def test_v2_single_match(self):
2464
- import fetch_soql # type: ignore
2465
- with self._stub_tooling([
2466
- {"Id": "1VxVF000V2", "DeveloperName": "Inbound_Sales_Agent_v2"},
2467
- ]):
2468
- row = fetch_soql.fetch_planner_definition(
2469
- "Inbound_Sales_Agent", "v2",
2470
- lambda: ("url", "tok"),
2471
- api_version="v66.0",
2472
- on_401_refresh=lambda: ("url", "tok"),
2473
- )
2474
- self.assertEqual(row["DeveloperName"], "Inbound_Sales_Agent_v2")
2475
-
2476
- def test_v2_multi_row_shortest_wins(self):
2477
- """LIKE `<Agent>%\\_v2` can match both `<Agent>_v2` and a deeper
2478
- chain like `<Agent>_foo_v2` (rare but possible). Shortest
2479
- DeveloperName wins — the canonical row carries no extra segment."""
2480
- import fetch_soql # type: ignore
2481
- with self._stub_tooling([
2482
- {"Id": "1VxVF000DEEPER",
2483
- "DeveloperName": "Inbound_Sales_Agent_foo_v2"},
2484
- {"Id": "1VxVF000V2",
2485
- "DeveloperName": "Inbound_Sales_Agent_v2"},
2486
- ]):
2487
- row = fetch_soql.fetch_planner_definition(
2488
- "Inbound_Sales_Agent", "v2",
2489
- lambda: ("url", "tok"),
2490
- api_version="v66.0",
2491
- on_401_refresh=lambda: ("url", "tok"),
2492
- )
2493
- self.assertEqual(row["DeveloperName"], "Inbound_Sales_Agent_v2")
2494
-
2495
- def test_zero_rows_returns_none(self):
2496
- import fetch_soql # type: ignore
2497
- with self._stub_tooling([]):
2498
- row = fetch_soql.fetch_planner_definition(
2499
- "NoSuchAgent", "v3",
2500
- lambda: ("url", "tok"),
2501
- api_version="v66.0",
2502
- on_401_refresh=lambda: ("url", "tok"),
2503
- )
2504
- self.assertIsNone(row)
2505
-
2506
- def test_chain_like_pattern_passed_to_soql_for_v5(self):
2507
- """The SOQL body that reaches `tooling_query` contains the chain
2508
- LIKE pattern literally. Verify AGENT_NAME + VERSION are rendered
2509
- through the template with the `%\\_` escape in between.
2510
- """
2511
- import fetch_soql # type: ignore
2512
- captured: dict = {}
2513
-
2514
- def fake_tooling(creds_provider, soql, *, api_version, on_401_refresh):
2515
- captured["soql"] = soql
2516
- return {"records": []}
2517
-
2518
- with mock.patch.object(fetch_soql, "tooling_query",
2519
- side_effect=fake_tooling):
2520
- fetch_soql.fetch_planner_definition(
2521
- "MyAgent", "v5",
2522
- lambda: ("url", "tok"),
2523
- api_version="v66.0",
2524
- on_401_refresh=lambda: ("url", "tok"),
2525
- )
2526
- self.assertIn("LIKE 'MyAgent%\\_v5'", captured["soql"])
2527
-
2528
-
2529
- class SwapDirAtomicCoTenancyTests(unittest.TestCase):
2530
- """`_swap_dir_atomic` preserves sibling content in `target`. The prior
2531
- whole-directory `os.replace` wiped any co-tenant subdirs that another
2532
- caller may have written into the same `<agent>__<ver>/` directory."""
2533
-
2534
- def test_preserves_sibling_session_dirs(self) -> None:
2535
- # Simulate co-tenancy: target dir already has a sibling subdir
2536
- # + a bare file written by some other caller.
2537
- with tempfile.TemporaryDirectory() as tmp:
2538
- tmp_p = Path(tmp)
2539
- target = tmp_p / "agent__v1"
2540
- target.mkdir()
2541
- (target / "sibling-data").mkdir()
2542
- (target / "sibling-data" / "payload.json").write_text(
2543
- "from-other-caller"
2544
- )
2545
- (target / "_sessions").mkdir()
2546
- (target / "_sessions" / "marker.link").write_text(
2547
- "../agent__v1/sibling-data"
2548
- )
2549
-
2550
- # Architecture's own previous output, about to be overwritten.
2551
- (target / "old_tree.json").write_text("old")
2552
-
2553
- # Staging dir — what architecture wants to write.
2554
- staging = tmp_p / ".agent__v1.staging.123"
2555
- staging.mkdir()
2556
- (staging / "agent_v1_metadata_tree.json").write_text("new-tree")
2557
- (staging / "last_built_at.txt").write_text("2026-05-05T12:00:00Z\n")
2558
-
2559
- main._swap_dir_atomic(target, staging)
2560
-
2561
- # Sibling content survives — the whole point of the fix.
2562
- self.assertTrue(
2563
- (target / "sibling-data" / "payload.json").is_file()
2564
- )
2565
- self.assertEqual(
2566
- (target / "sibling-data" / "payload.json").read_text(),
2567
- "from-other-caller",
2568
- )
2569
- self.assertTrue((target / "_sessions" / "marker.link").is_file())
2570
-
2571
- # Architecture's new files landed.
2572
- self.assertEqual(
2573
- (target / "agent_v1_metadata_tree.json").read_text(), "new-tree"
2574
- )
2575
- self.assertTrue((target / "last_built_at.txt").is_file())
2576
-
2577
- # Old file that wasn't in staging stays untouched.
2578
- self.assertTrue((target / "old_tree.json").is_file())
2579
- self.assertEqual((target / "old_tree.json").read_text(), "old")
2580
-
2581
- # Staging dir cleaned up.
2582
- self.assertFalse(staging.exists())
2583
-
2584
- def test_overwrites_own_files_cleanly(self) -> None:
2585
- """Same filename in both target and staging → staging content wins."""
2586
- with tempfile.TemporaryDirectory() as tmp:
2587
- tmp_p = Path(tmp)
2588
- target = tmp_p / "agent__v1"
2589
- target.mkdir()
2590
- (target / "tree.json").write_text("old-content")
2591
-
2592
- staging = tmp_p / ".agent__v1.staging.123"
2593
- staging.mkdir()
2594
- (staging / "tree.json").write_text("new-content")
2595
-
2596
- main._swap_dir_atomic(target, staging)
2597
-
2598
- self.assertEqual(
2599
- (target / "tree.json").read_text(), "new-content"
2600
- )
2601
-
2602
- def test_overwrites_when_target_entry_is_dir(self) -> None:
2603
- """If the old target entry is a directory and the new staging
2604
- entry is a file (or vice versa), replace cleans up the old kind
2605
- before os.replace lands the new one."""
2606
- with tempfile.TemporaryDirectory() as tmp:
2607
- tmp_p = Path(tmp)
2608
- target = tmp_p / "agent__v1"
2609
- target.mkdir()
2610
- # Old entry is a directory with nested content.
2611
- (target / "payload").mkdir()
2612
- (target / "payload" / "nested.txt").write_text("deep")
2613
-
2614
- staging = tmp_p / ".agent__v1.staging.123"
2615
- staging.mkdir()
2616
- # New entry with the same name is a plain file.
2617
- (staging / "payload").write_text("now-a-file")
2618
-
2619
- main._swap_dir_atomic(target, staging)
2620
-
2621
- self.assertTrue((target / "payload").is_file())
2622
- self.assertEqual(
2623
- (target / "payload").read_text(), "now-a-file"
2624
- )
2625
-
2626
- def test_missing_staging_raises(self) -> None:
2627
- """Pre-existing precondition: staging must exist, or we raise."""
2628
- with tempfile.TemporaryDirectory() as tmp:
2629
- tmp_p = Path(tmp)
2630
- target = tmp_p / "agent__v1"
2631
- target.mkdir()
2632
- staging = tmp_p / ".agent__v1.staging.does-not-exist"
2633
- with self.assertRaises(OSError):
2634
- main._swap_dir_atomic(target, staging)
2635
-
2636
- def test_run_finalize_preserves_session_subdir_across_reruns(self) -> None:
2637
- """End-to-end via `_run_finalize`: after a first successful run
2638
- seeds a co-tenant session dir, a second run must not wipe it.
2639
- Covers the production path — the bug the user reported."""
2640
- with tempfile.TemporaryDirectory() as tmp:
2641
- tmp_p = Path(tmp)
2642
- work_dir = tmp_p / "work"
2643
- work_dir.mkdir()
2644
- data_dir = tmp_p / "data" / "A__v1"
2645
- cache_dir = tmp_p / "cache" / "A__v1"
2646
-
2647
- tree = {
2648
- "_schema_version": "3.0",
2649
- "agent": {"api_name": "A", "version": "v1"},
2650
- "root": {"kind": "BOT_DEFINITION", "api_name": "A",
2651
- "children": []},
2652
- "node_count": 1, "depth": 0,
2653
- "_kind_counts": {"BOT_DEFINITION": 1},
2654
- "_pending_fetches": {k: [] for k in (
2655
- "FLOW", "APEX", "PROMPT_TEMPLATE", "STANDARD_ACTION",
2656
- )},
2657
- "_unresolved": [],
2658
- }
2659
- # First run — populate data_dir.
2660
- main._run_finalize(
2661
- data_dir, cache_dir, dict(tree), work_dir,
2662
- agent_api_name="A", agent_version="v1", planner_name="A",
2663
- )
2664
- # Simulate a co-tenant dropping content alongside.
2665
- sibling_dir = data_dir / "sibling-payload"
2666
- sibling_dir.mkdir()
2667
- (sibling_dir / "payload.json").write_text("cotenant-data")
2668
-
2669
- # Second run — the original bug: this would wipe the sibling dir.
2670
- main._run_finalize(
2671
- data_dir, cache_dir, dict(tree), work_dir,
2672
- agent_api_name="A", agent_version="v1", planner_name="A",
2673
- )
2674
-
2675
- # Sibling dir and its contents must survive.
2676
- self.assertTrue(sibling_dir.is_dir())
2677
- self.assertTrue((sibling_dir / "payload.json").is_file())
2678
- self.assertEqual(
2679
- (sibling_dir / "payload.json").read_text(),
2680
- "cotenant-data",
2681
- )
2682
- # Architecture's own tree is still present (re-written).
2683
- self.assertTrue((data_dir / "A_v1_metadata_tree.json").is_file())
2684
-
2685
-
2686
- # ---------------------------------------------------------------------------
2687
- # Bug 1 fix (2026-05-05): GenAiPromptTemplate is NOT SOQL-queryable. Id →
2688
- # DeveloperName resolution runs through `sf org list metadata` (Metadata
2689
- # API) via the new `list_prompt_template_metadata` helper.
2690
- # ---------------------------------------------------------------------------
2691
-
2692
-
2693
- class ListPromptTemplateMetadataTests(unittest.TestCase):
2694
- """Unit tests for `metadata_listing.list_prompt_template_metadata` —
2695
- thin wrapper over `run_sf("list_metadata_genaiprompttemplate", ...)`.
2696
-
2697
- The shape we care about is produced by the sf CLI:
2698
- {"status": 0, "result": [{"id": "0hfUv...", "fullName": "Foo", ...}]}
2699
- Defensive returns on malformed result (None / wrong type) keep the
2700
- failure mode quiet — callers already tolerate empty lists.
2701
- """
2702
-
2703
- def test_happy_path_returns_result_rows(self):
2704
- import metadata_listing # type: ignore
2705
- payload = {
2706
- "status": 0,
2707
- "result": [
2708
- {"id": "0hfUv0000021mCjIAI", "fullName": "My_Prompt",
2709
- "type": "GenAiPromptTemplate"},
2710
- {"id": "0hfUv0000021mOtherAAA", "fullName": "Other_Prompt",
2711
- "type": "GenAiPromptTemplate"},
2712
- ],
2713
- }
2714
- with mock.patch.object(metadata_listing, "run_sf", return_value=payload):
2715
- rows = metadata_listing.list_prompt_template_metadata("test-org")
2716
- self.assertEqual(rows, payload["result"])
2717
-
2718
- def test_empty_result_returns_empty_list(self):
2719
- import metadata_listing # type: ignore
2720
- with mock.patch.object(
2721
- metadata_listing, "run_sf",
2722
- return_value={"status": 0, "result": []},
2723
- ):
2724
- rows = metadata_listing.list_prompt_template_metadata("test-org")
2725
- self.assertEqual(rows, [])
2726
-
2727
- def test_malformed_result_returns_empty_list(self):
2728
- """Defensive: if sf CLI's `result` key is not a list (e.g. None
2729
- on some error paths that still exit 0), we degrade to []."""
2730
- import metadata_listing # type: ignore
2731
- with mock.patch.object(
2732
- metadata_listing, "run_sf",
2733
- return_value={"status": 0, "result": None},
2734
- ):
2735
- rows = metadata_listing.list_prompt_template_metadata("test-org")
2736
- self.assertEqual(rows, [])
2737
-
2738
-
2739
- class FetchWaveBPromptTemplateMetadataWiringTests(unittest.TestCase):
2740
- """Bug 1 fix (2026-05-05): `_fetch_wave_b_by_names` invokes
2741
- `list_prompt_template_metadata` (Metadata API listing), then filters +
2742
- reshapes to the {Id, DeveloperName} shape the downstream pipeline
2743
- expects. Verify the filter + reshape contract — only the requested
2744
- Ids come back, keyed as the pipeline's existing prompt_template_id_rows
2745
- shape.
2746
- """
2747
-
2748
- def test_listmetadata_rows_filtered_and_reshaped(self):
2749
- with mock.patch.object(
2750
- main, "list_prompt_template_metadata",
2751
- return_value=[
2752
- {"id": "0hfAAA", "fullName": "TplA",
2753
- "type": "GenAiPromptTemplate"},
2754
- {"id": "0hfBBB", "fullName": "TplB",
2755
- "type": "GenAiPromptTemplate"},
2756
- ],
2757
- ):
2758
- with mock.patch.object(main, "fetch_apex_bodies_by_names", return_value=[]), \
2759
- mock.patch.object(main, "fetch_apex_bodies_by_ids", return_value=[]), \
2760
- mock.patch.object(main, "fetch_flow_definition_ids_by_names", return_value=[]), \
2761
- mock.patch.object(main, "fetch_flow_definition_by_ids", return_value=[]):
2762
- out = main._fetch_wave_b_by_names(
2763
- apex_names=[],
2764
- apex_ids=[],
2765
- flow_names=[],
2766
- flow_ids=[],
2767
- prompt_template_ids=["0hfAAA"],
2768
- creds_provider=lambda: ("url", "tok"),
2769
- refresh_fn=lambda: ("url", "tok"),
2770
- api_version="v60.0",
2771
- org_alias="test-org",
2772
- parallelism=2,
2773
- )
2774
- # Only the requested Id survives (0hfAAA); 0hfBBB is filtered out.
2775
- # The shape matches the old SOQL contract: {Id, DeveloperName}.
2776
- self.assertEqual(
2777
- out["prompt_template_id_rows"],
2778
- [{"Id": "0hfAAA", "DeveloperName": "TplA"}],
2779
- )
2780
-
2781
- def test_listmetadata_failure_non_fatal(self):
2782
- """SfCliError from the Metadata listing is caught and surfaced via
2783
- the unresolved channel; the run continues with an empty rowset."""
2784
- from sf_cli import SfCliError # type: ignore
2785
- with mock.patch.object(
2786
- main, "list_prompt_template_metadata",
2787
- side_effect=SfCliError("metadata-listing-exploded"),
2788
- ):
2789
- with mock.patch.object(main, "fetch_apex_bodies_by_names", return_value=[]), \
2790
- mock.patch.object(main, "fetch_apex_bodies_by_ids", return_value=[]), \
2791
- mock.patch.object(main, "fetch_flow_definition_ids_by_names", return_value=[]), \
2792
- mock.patch.object(main, "fetch_flow_definition_by_ids", return_value=[]):
2793
- out = main._fetch_wave_b_by_names(
2794
- apex_names=[],
2795
- apex_ids=[],
2796
- flow_names=[],
2797
- flow_ids=[],
2798
- prompt_template_ids=["0hfAAA"],
2799
- creds_provider=lambda: ("url", "tok"),
2800
- refresh_fn=lambda: ("url", "tok"),
2801
- api_version="v60.0",
2802
- org_alias="test-org",
2803
- parallelism=2,
2804
- )
2805
- self.assertEqual(out["prompt_template_id_rows"], [])
2806
- reasons = [u.get("reason") or "" for u in out["unresolved"]]
2807
- self.assertTrue(
2808
- any("prompt-template-listmetadata-failed" in r for r in reasons),
2809
- f"expected listmetadata-failed in unresolved; got {reasons}",
2810
- )
2811
-
2812
-
2813
- class RetrievePromptTemplatesTests(unittest.TestCase):
2814
- """Gap C (2026-05-05): unit tests for
2815
- `metadata_listing.retrieve_prompt_templates` — the sf CLI wrapper
2816
- that retrieves GenAiPromptTemplate bodies via
2817
- `sf project retrieve start --metadata GenAiPromptTemplate:...`.
2818
-
2819
- The helper:
2820
- 1. Short-circuits on empty input (no sf call).
2821
- 2. Parses `unpackaged.zip` from the retrieve dir via stdlib
2822
- `zipfile` + `xml.etree.ElementTree`.
2823
- 3. Extracts developerName/masterLabel/activeVersionIdentifier/
2824
- templateVersions[*].content/inputs[*].
2825
- 4. Returns `{}` on SfCliError (non-fatal — main.py's call site
2826
- logs an `_unresolved[]` entry).
2827
- 5. Skips files whose XML fails to parse; sibling templates still
2828
- surface.
2829
- """
2830
-
2831
- def _run_retrieve_writes_zip(self, files: dict):
2832
- """Build a mock `_run_retrieve` side_effect that writes an
2833
- unpackaged.zip into the retrieve dir as the real CLI would.
2834
-
2835
- `files = {inner_path: xml_bytes}`. `retrieve_prompt_templates`
2836
- wipes the retrieve dir before invoking the subprocess, so the zip
2837
- MUST be created by the mock (the retrieve dir is always the
2838
- `--target-metadata-dir` argv element)."""
2839
- import zipfile
2840
-
2841
- def _side_effect(argv, timeout):
2842
- target_dir = Path(argv[argv.index("--target-metadata-dir") + 1])
2843
- target_dir.mkdir(parents=True, exist_ok=True)
2844
- zip_path = target_dir / "unpackaged.zip"
2845
- with zipfile.ZipFile(zip_path, "w") as zf:
2846
- for inner, xml_bytes in files.items():
2847
- zf.writestr(inner, xml_bytes)
2848
- return subprocess.CompletedProcess(
2849
- argv, returncode=0, stdout='{"status":0,"result":{}}', stderr="",
2850
- )
2851
-
2852
- return _side_effect
2853
-
2854
- def test_empty_input_short_circuits_without_sf_call(self):
2855
- import metadata_listing # type: ignore
2856
- with mock.patch.object(metadata_listing, "_run_retrieve") as mrun, \
2857
- tempfile.TemporaryDirectory() as d:
2858
- result = metadata_listing.retrieve_prompt_templates(
2859
- "org-alias", [], Path(d),
2860
- )
2861
- self.assertEqual(result, {})
2862
- mrun.assert_not_called()
2863
-
2864
- def test_happy_path_single_template(self):
2865
- import metadata_listing # type: ignore
2866
- xml = (
2867
- b'<?xml version="1.0" encoding="UTF-8"?>'
2868
- b'<GenAiPromptTemplate xmlns="http://soap.sforce.com/2006/04/metadata">'
2869
- b'<developerName>My_Prompt</developerName>'
2870
- b'<masterLabel>My Prompt</masterLabel>'
2871
- b'<activeVersionIdentifier>v1</activeVersionIdentifier>'
2872
- b'<templateVersions>'
2873
- b'<versionIdentifier>v1</versionIdentifier>'
2874
- b'<content># ROLE\nHello {{$Input:Query}}</content>'
2875
- b'<inputs><apiName>Query</apiName><dataType>String</dataType></inputs>'
2876
- b'</templateVersions>'
2877
- b'</GenAiPromptTemplate>'
2878
- )
2879
- with tempfile.TemporaryDirectory() as d:
2880
- tmp = Path(d)
2881
- side_effect = self._run_retrieve_writes_zip({
2882
- "unpackaged/genAiPromptTemplates/My_Prompt.genAiPromptTemplate": xml,
2883
- "unpackaged/package.xml": b"<Package/>",
2884
- })
2885
- with mock.patch.object(
2886
- metadata_listing, "_run_retrieve", side_effect=side_effect,
2887
- ):
2888
- result = metadata_listing.retrieve_prompt_templates(
2889
- "org-alias", ["My_Prompt"], tmp,
2890
- )
2891
- self.assertIn("My_Prompt", result)
2892
- body = result["My_Prompt"]
2893
- self.assertEqual(body["developerName"], "My_Prompt")
2894
- self.assertEqual(body["masterLabel"], "My Prompt")
2895
- self.assertEqual(body["activeVersionIdentifier"], "v1")
2896
- self.assertEqual(body["content"], "# ROLE\nHello {{$Input:Query}}")
2897
- self.assertEqual(
2898
- body["inputs"], [{"name": "Query", "dataType": "String"}],
2899
- )
2900
-
2901
- def test_sf_cli_error_returns_empty_dict(self):
2902
- """Non-zero exit without auth-pattern stderr is swallowed as
2903
- non-fatal — caller gets an empty dict."""
2904
- import metadata_listing # type: ignore
2905
- failure = subprocess.CompletedProcess(
2906
- args=[], returncode=1, stdout="", stderr="Error: retrieve blew up",
2907
- )
2908
- with tempfile.TemporaryDirectory() as d:
2909
- with mock.patch.object(
2910
- metadata_listing, "_run_retrieve", return_value=failure,
2911
- ):
2912
- result = metadata_listing.retrieve_prompt_templates(
2913
- "org-alias", ["Foo"], Path(d),
2914
- )
2915
- self.assertEqual(result, {})
2916
-
2917
- def test_auth_required_reraises(self):
2918
- """Non-zero exit WITH auth-pattern stderr raises AuthRequired."""
2919
- import metadata_listing # type: ignore
2920
- from sf_cli import AuthRequired # type: ignore
2921
- failure = subprocess.CompletedProcess(
2922
- args=[], returncode=1, stdout="",
2923
- stderr="Error: NoOrgAuthenticationError — login required",
2924
- )
2925
- with tempfile.TemporaryDirectory() as d:
2926
- with mock.patch.object(
2927
- metadata_listing, "_run_retrieve", return_value=failure,
2928
- ):
2929
- with self.assertRaises(AuthRequired):
2930
- metadata_listing.retrieve_prompt_templates(
2931
- "org-alias", ["Foo"], Path(d),
2932
- )
2933
-
2934
- def test_missing_zip_returns_empty_dict(self):
2935
- import metadata_listing # type: ignore
2936
- # _run_retrieve succeeds but leaves no unpackaged.zip on disk.
2937
- success_no_zip = subprocess.CompletedProcess(
2938
- args=[], returncode=0, stdout='{"status":0,"result":{}}', stderr="",
2939
- )
2940
- with tempfile.TemporaryDirectory() as d:
2941
- with mock.patch.object(
2942
- metadata_listing, "_run_retrieve", return_value=success_no_zip,
2943
- ):
2944
- result = metadata_listing.retrieve_prompt_templates(
2945
- "org-alias", ["Foo"], Path(d),
2946
- )
2947
- self.assertEqual(result, {})
2948
-
2949
- def test_multi_version_picks_active(self):
2950
- import metadata_listing # type: ignore
2951
- xml = (
2952
- b'<?xml version="1.0" encoding="UTF-8"?>'
2953
- b'<GenAiPromptTemplate xmlns="http://soap.sforce.com/2006/04/metadata">'
2954
- b'<developerName>Versioned</developerName>'
2955
- b'<activeVersionIdentifier>v2</activeVersionIdentifier>'
2956
- b'<templateVersions>'
2957
- b'<versionIdentifier>v1</versionIdentifier>'
2958
- b'<content>OLD</content>'
2959
- b'</templateVersions>'
2960
- b'<templateVersions>'
2961
- b'<versionIdentifier>v2</versionIdentifier>'
2962
- b'<content>ACTIVE</content>'
2963
- b'</templateVersions>'
2964
- b'<templateVersions>'
2965
- b'<versionIdentifier>v3</versionIdentifier>'
2966
- b'<content>DRAFT</content>'
2967
- b'</templateVersions>'
2968
- b'</GenAiPromptTemplate>'
2969
- )
2970
- with tempfile.TemporaryDirectory() as d:
2971
- tmp = Path(d)
2972
- side_effect = self._run_retrieve_writes_zip({
2973
- "unpackaged/genAiPromptTemplates/Versioned.genAiPromptTemplate": xml,
2974
- })
2975
- with mock.patch.object(
2976
- metadata_listing, "_run_retrieve", side_effect=side_effect,
2977
- ):
2978
- result = metadata_listing.retrieve_prompt_templates(
2979
- "org-alias", ["Versioned"], tmp,
2980
- )
2981
- self.assertEqual(result["Versioned"]["content"], "ACTIVE")
2982
-
2983
- def test_template_with_no_inputs(self):
2984
- import metadata_listing # type: ignore
2985
- xml = (
2986
- b'<?xml version="1.0" encoding="UTF-8"?>'
2987
- b'<GenAiPromptTemplate xmlns="http://soap.sforce.com/2006/04/metadata">'
2988
- b'<developerName>NoInputs</developerName>'
2989
- b'<activeVersionIdentifier>v1</activeVersionIdentifier>'
2990
- b'<templateVersions>'
2991
- b'<versionIdentifier>v1</versionIdentifier>'
2992
- b'<content>Prompt body</content>'
2993
- b'</templateVersions>'
2994
- b'</GenAiPromptTemplate>'
2995
- )
2996
- with tempfile.TemporaryDirectory() as d:
2997
- tmp = Path(d)
2998
- side_effect = self._run_retrieve_writes_zip({
2999
- "unpackaged/genAiPromptTemplates/NoInputs.genAiPromptTemplate": xml,
3000
- })
3001
- with mock.patch.object(
3002
- metadata_listing, "_run_retrieve", side_effect=side_effect,
3003
- ):
3004
- result = metadata_listing.retrieve_prompt_templates(
3005
- "org-alias", ["NoInputs"], tmp,
3006
- )
3007
- self.assertEqual(result["NoInputs"]["inputs"], [])
3008
-
3009
- def test_xml_parse_failure_skips_file_continues(self):
3010
- """Malformed XML on one template must not prevent sibling
3011
- templates from surfacing."""
3012
- import metadata_listing # type: ignore
3013
- good_xml = (
3014
- b'<?xml version="1.0" encoding="UTF-8"?>'
3015
- b'<GenAiPromptTemplate xmlns="http://soap.sforce.com/2006/04/metadata">'
3016
- b'<developerName>GoodTpl</developerName>'
3017
- b'<activeVersionIdentifier>v1</activeVersionIdentifier>'
3018
- b'<templateVersions>'
3019
- b'<versionIdentifier>v1</versionIdentifier>'
3020
- b'<content>Fine</content>'
3021
- b'</templateVersions>'
3022
- b'</GenAiPromptTemplate>'
3023
- )
3024
- broken_xml = b"<not valid xml"
3025
- with tempfile.TemporaryDirectory() as d:
3026
- tmp = Path(d)
3027
- side_effect = self._run_retrieve_writes_zip({
3028
- "unpackaged/genAiPromptTemplates/GoodTpl.genAiPromptTemplate": good_xml,
3029
- "unpackaged/genAiPromptTemplates/Broken.genAiPromptTemplate": broken_xml,
3030
- })
3031
- with mock.patch.object(
3032
- metadata_listing, "_run_retrieve", side_effect=side_effect,
3033
- ):
3034
- result = metadata_listing.retrieve_prompt_templates(
3035
- "org-alias", ["GoodTpl", "Broken"], tmp,
3036
- )
3037
- self.assertIn("GoodTpl", result)
3038
- self.assertNotIn("Broken", result)
3039
-
3040
- def test_stale_retrieve_dir_contents_wiped(self):
3041
- """A prior invocation's `unpackaged.zip` must not be trusted if
3042
- this run's sf call fails before writing a new one."""
3043
- import metadata_listing # type: ignore
3044
- failure = subprocess.CompletedProcess(
3045
- args=[], returncode=1, stdout="", stderr="Error: boom",
3046
- )
3047
- with tempfile.TemporaryDirectory() as d:
3048
- tmp = Path(d)
3049
- # Plant a stale zip pretending a prior run left it.
3050
- stale = tmp / "prompt_template_retrieve"
3051
- stale.mkdir(parents=True, exist_ok=True)
3052
- (stale / "unpackaged.zip").write_bytes(b"stale")
3053
- with mock.patch.object(
3054
- metadata_listing, "_run_retrieve", return_value=failure,
3055
- ):
3056
- result = metadata_listing.retrieve_prompt_templates(
3057
- "org-alias", ["Foo"], tmp,
3058
- )
3059
- self.assertEqual(result, {})
3060
- # Stale file should have been nuked before the sf call.
3061
- self.assertFalse((stale / "unpackaged.zip").exists())
3062
-
3063
- def test_retrieve_builds_one_metadata_flag_per_name(self):
3064
- """Live proof (2026-05-05): `sf project retrieve start` treats a
3065
- comma-joined `--metadata TypeA:A,TypeA:B` as ONE malformed member
3066
- name and silently produces a package-xml-only zip. The fix is to
3067
- repeat `--metadata` once per template. Lock that shape in."""
3068
- import metadata_listing # type: ignore
3069
- captured_argv: list[list[str]] = []
3070
-
3071
- def _capture(argv, timeout):
3072
- captured_argv.append(list(argv))
3073
- return subprocess.CompletedProcess(
3074
- argv, returncode=0,
3075
- stdout='{"status":0,"result":{}}', stderr="",
3076
- )
3077
-
3078
- with tempfile.TemporaryDirectory() as d:
3079
- with mock.patch.object(
3080
- metadata_listing, "_run_retrieve", side_effect=_capture,
3081
- ):
3082
- metadata_listing.retrieve_prompt_templates(
3083
- "org-alias", ["A", "B", "C"], Path(d),
3084
- )
3085
-
3086
- self.assertEqual(len(captured_argv), 1)
3087
- argv = captured_argv[0]
3088
- self.assertEqual(argv.count("--metadata"), 3)
3089
- # Each `--metadata` flag MUST be followed by a single
3090
- # `GenAiPromptTemplate:<name>` — never a comma-joined string.
3091
- for name in ("A", "B", "C"):
3092
- spec = f"GenAiPromptTemplate:{name}"
3093
- idx = argv.index(spec)
3094
- self.assertEqual(argv[idx - 1], "--metadata")
3095
- self.assertNotIn(",", spec)
3096
-
3097
-
3098
- class CollectPromptTemplateNamesTests(unittest.TestCase):
3099
- """Gap C: `_collect_prompt_template_names` walks topics + plannerActions
3100
- and returns the set of DeveloperNames that should be passed to
3101
- `retrieve_prompt_templates`. Defensive against residual 0hf-Ids
3102
- (normalization missed) so the retrieve CLI doesn't get a malformed
3103
- spec."""
3104
-
3105
- def test_collects_topic_action_names(self):
3106
- bundle = {
3107
- "topics": [{
3108
- "actions": [
3109
- {"invocationTarget": "Foo_Tpl",
3110
- "invocationTargetType": "GenAiPromptTemplate"},
3111
- {"invocationTarget": "Bar_Tpl",
3112
- "invocationTargetType": "generatePromptResponse"},
3113
- ],
3114
- }],
3115
- "plannerActions": [],
3116
- }
3117
- names = main._collect_prompt_template_names(bundle)
3118
- self.assertEqual(names, {"Foo_Tpl", "Bar_Tpl"})
3119
-
3120
- def test_collects_planner_action_names(self):
3121
- bundle = {
3122
- "topics": [],
3123
- "plannerActions": [
3124
- {"invocationTarget": "Planner_Tpl",
3125
- "invocationTargetType": "GenAiPromptTemplate"},
3126
- ],
3127
- }
3128
- names = main._collect_prompt_template_names(bundle)
3129
- self.assertEqual(names, {"Planner_Tpl"})
3130
-
3131
- def test_skips_non_prompt_ttype(self):
3132
- bundle = {
3133
- "topics": [{
3134
- "actions": [
3135
- {"invocationTarget": "MyFlow",
3136
- "invocationTargetType": "flow"},
3137
- {"invocationTarget": "MyApex",
3138
- "invocationTargetType": "apex"},
3139
- ],
3140
- }],
3141
- "plannerActions": [],
3142
- }
3143
- names = main._collect_prompt_template_names(bundle)
3144
- self.assertEqual(names, set())
3145
-
3146
- def test_skips_residual_0hf_id_targets(self):
3147
- """If normalization missed an Id (template not in org
3148
- list-metadata), don't send a malformed spec to retrieve."""
3149
- bundle = {
3150
- "topics": [{
3151
- "actions": [
3152
- {"invocationTarget": "0hfUv0000021mCjIAI",
3153
- "invocationTargetType": "GenAiPromptTemplate"},
3154
- {"invocationTarget": "Clean_Tpl",
3155
- "invocationTargetType": "GenAiPromptTemplate"},
3156
- ],
3157
- }],
3158
- "plannerActions": [],
3159
- }
3160
- names = main._collect_prompt_template_names(bundle)
3161
- self.assertEqual(names, {"Clean_Tpl"})
3162
-
3163
-
3164
- class PromptTemplateBodyAttachmentTests(unittest.TestCase):
3165
- """Gap C: `_stamp_prompt_template_bodies` attaches retrieved body
3166
- fields onto matching PROMPT_TEMPLATE leaves. Unmatched leaves get
3167
- `_body_available = False` so the renderer can distinguish a failed
3168
- retrieve from a successfully-empty body."""
3169
-
3170
- def test_stamps_body_onto_matching_leaf(self):
3171
- tree = {
3172
- "root": {
3173
- "kind": "BOT_DEFINITION",
3174
- "children": [{
3175
- "kind": "TOPIC", "api_name": "T",
3176
- "children": [{
3177
- "kind": "GEN_AI_FUNCTION", "api_name": "F",
3178
- "children": [{
3179
- "kind": "PROMPT_TEMPLATE", "api_name": "Tpl",
3180
- }],
3181
- }],
3182
- }],
3183
- },
3184
- }
3185
- bodies = {
3186
- "Tpl": {
3187
- "developerName": "Tpl",
3188
- "masterLabel": "Template One",
3189
- "activeVersionIdentifier": "v1",
3190
- "content": "Prompt body",
3191
- "inputs": [{"name": "Q", "dataType": "String"}],
3192
- },
3193
- }
3194
- main._stamp_prompt_template_bodies(tree["root"], bodies)
3195
- leaf = tree["root"]["children"][0]["children"][0]["children"][0]
3196
- self.assertEqual(leaf["master_label"], "Template One")
3197
- self.assertEqual(leaf["content"], "Prompt body")
3198
- self.assertEqual(leaf["inputs"], [{"name": "Q", "dataType": "String"}])
3199
- self.assertTrue(leaf["_body_available"])
3200
-
3201
- def test_unmatched_leaf_gets_body_available_false(self):
3202
- tree = {
3203
- "root": {
3204
- "kind": "BOT_DEFINITION",
3205
- "children": [{
3206
- "kind": "PROMPT_TEMPLATE", "api_name": "Missing",
3207
- }],
3208
- },
3209
- }
3210
- main._stamp_prompt_template_bodies(tree["root"], {})
3211
- self.assertFalse(tree["root"]["children"][0]["_body_available"])
3212
- self.assertNotIn("content", tree["root"]["children"][0])
3213
-
3214
- def test_does_not_touch_non_prompt_leaves(self):
3215
- tree = {
3216
- "root": {
3217
- "kind": "BOT_DEFINITION",
3218
- "children": [
3219
- {"kind": "APEX", "api_name": "Cls"},
3220
- {"kind": "FLOW", "api_name": "Flw"},
3221
- ],
3222
- },
3223
- }
3224
- main._stamp_prompt_template_bodies(
3225
- tree["root"], {"Cls": {"content": "x"}, "Flw": {"content": "y"}},
3226
- )
3227
- # Neither APEX nor FLOW leaves gain body fields.
3228
- self.assertNotIn("content", tree["root"]["children"][0])
3229
- self.assertNotIn("_body_available", tree["root"]["children"][0])
3230
- self.assertNotIn("content", tree["root"]["children"][1])
3231
- self.assertNotIn("_body_available", tree["root"]["children"][1])
3232
-
3233
-
3234
- class TreeChildOrderingTests(unittest.TestCase):
3235
- """Schema 3.1 (2026-05-05) pins deterministic child ordering at the
3236
- tree's single source of truth (`finalize.sort_tree_in_place`) so
3237
- downstream readers see a byte-stable order regardless of Builder
3238
- reorder operations or SOQL result-set sequencing.
3239
-
3240
- Contract:
3241
- - `BOT_DEFINITION.children`: TOPIC nodes first (alpha, case-insensitive);
3242
- non-topic plannerActions follow as a distinct trailing group.
3243
- - Each TOPIC's children: alpha by api_name, case-insensitive.
3244
- - FLOW children untouched — flow-actionCall order is semantically
3245
- the author's execution sequence.
3246
- """
3247
-
3248
- def _sort(self, root: dict) -> dict:
3249
- from finalize import sort_tree_in_place
3250
- sort_tree_in_place(root)
3251
- return root
3252
-
3253
- def test_topics_sorted_alphabetical_case_insensitive(self):
3254
- root = {
3255
- "kind": "BOT_DEFINITION",
3256
- "api_name": "Bot",
3257
- "children": [
3258
- {"kind": "TOPIC", "api_name": "Zeta", "children": []},
3259
- {"kind": "TOPIC", "api_name": "alpha", "children": []},
3260
- {"kind": "TOPIC", "api_name": "Mike", "children": []},
3261
- ],
3262
- }
3263
- self._sort(root)
3264
- names = [c["api_name"] for c in root["children"]]
3265
- self.assertEqual(names, ["alpha", "Mike", "Zeta"])
3266
-
3267
- def test_topics_precede_planner_level_actions(self):
3268
- """Non-topic plannerAction children (e.g. a GEN_AI_FUNCTION hung
3269
- directly off the planner, no parent TOPIC) MUST render after all
3270
- TOPIC children, regardless of api_name ordering. The "planner-
3271
- level actions are a distinct trailing group" convention is load-
3272
- bearing for humans scanning the rendered tree."""
3273
- root = {
3274
- "kind": "BOT_DEFINITION",
3275
- "api_name": "Bot",
3276
- "children": [
3277
- # Non-topic node with an api_name that would sort FIRST
3278
- # alphabetically — the tier rule must override alpha.
3279
- {"kind": "GEN_AI_FUNCTION", "api_name": "aaa_action", "children": []},
3280
- {"kind": "TOPIC", "api_name": "Zeta", "children": []},
3281
- {"kind": "TOPIC", "api_name": "Mike", "children": []},
3282
- ],
3283
- }
3284
- self._sort(root)
3285
- kinds = [c["kind"] for c in root["children"]]
3286
- self.assertEqual(kinds, ["TOPIC", "TOPIC", "GEN_AI_FUNCTION"])
3287
- # Alpha within the TOPIC tier is preserved.
3288
- self.assertEqual(root["children"][0]["api_name"], "Mike")
3289
- self.assertEqual(root["children"][1]["api_name"], "Zeta")
3290
-
3291
- def test_topic_children_sorted_alphabetical(self):
3292
- root = {
3293
- "kind": "BOT_DEFINITION",
3294
- "api_name": "Bot",
3295
- "children": [
3296
- {
3297
- "kind": "TOPIC", "api_name": "OnlyTopic",
3298
- "children": [
3299
- {"kind": "GEN_AI_FUNCTION", "api_name": "Zebra"},
3300
- {"kind": "GEN_AI_FUNCTION", "api_name": "apple"},
3301
- {"kind": "GEN_AI_FUNCTION", "api_name": "Mango"},
3302
- ],
3303
- },
3304
- ],
3305
- }
3306
- self._sort(root)
3307
- kids = root["children"][0]["children"]
3308
- self.assertEqual(
3309
- [c["api_name"] for c in kids],
3310
- ["apple", "Mango", "Zebra"],
3311
- )
3312
-
3313
- def test_flow_children_order_preserved(self):
3314
- """FLOW actionCall order is the flow author's execution sequence.
3315
- sort_tree_in_place does NOT descend into FLOW children."""
3316
- root = {
3317
- "kind": "BOT_DEFINITION",
3318
- "api_name": "Bot",
3319
- "children": [
3320
- {
3321
- "kind": "TOPIC", "api_name": "T",
3322
- "children": [
3323
- {
3324
- "kind": "GEN_AI_FUNCTION", "api_name": "Fn",
3325
- "children": [
3326
- {
3327
- "kind": "FLOW", "api_name": "ParentFlow",
3328
- "children": [
3329
- {"kind": "APEX", "api_name": "zzz"},
3330
- {"kind": "APEX", "api_name": "aaa"},
3331
- ],
3332
- },
3333
- ],
3334
- },
3335
- ],
3336
- },
3337
- ],
3338
- }
3339
- self._sort(root)
3340
- flow = root["children"][0]["children"][0]["children"][0]
3341
- self.assertEqual(
3342
- [c["api_name"] for c in flow["children"]],
3343
- ["zzz", "aaa"],
3344
- )
3345
-
3346
- def test_empty_children_noop(self):
3347
- root = {"kind": "BOT_DEFINITION", "api_name": "Bot", "children": []}
3348
- self._sort(root)
3349
- self.assertEqual(root["children"], [])
3350
-
3351
- def test_missing_root_noop(self):
3352
- """Defensive — a degenerate tree shouldn't raise."""
3353
- from finalize import sort_tree_in_place
3354
- sort_tree_in_place(None) # type: ignore[arg-type]
3355
- sort_tree_in_place({})
3356
-
3357
-
3358
- if __name__ == "__main__":
3359
- unittest.main()