@salesforce/afv-skills 1.22.0 → 1.23.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 (1668) hide show
  1. package/package.json +1 -1
  2. package/skills/activating-datacloud/README.md +0 -39
  3. package/skills/activating-datacloud/SKILL.md +0 -117
  4. package/skills/analyzing-omnistudio-dependencies/CREDITS.md +0 -5
  5. package/skills/analyzing-omnistudio-dependencies/SKILL.md +0 -476
  6. package/skills/analyzing-omnistudio-dependencies/references/dependency-patterns.md +0 -508
  7. package/skills/analyzing-omnistudio-dependencies/references/namespace-guide.md +0 -300
  8. package/skills/applying-cms-brand/SKILL.md +0 -170
  9. package/skills/applying-slds/SKILL.md +0 -322
  10. package/skills/applying-slds/checklists.md +0 -83
  11. package/skills/applying-slds/examples.md +0 -283
  12. package/skills/applying-slds/guidance/README.md +0 -83
  13. package/skills/applying-slds/guidance/blueprints-index.md +0 -213
  14. package/skills/applying-slds/guidance/icons-guidance.md +0 -186
  15. package/skills/applying-slds/guidance/overviews/borders.md +0 -236
  16. package/skills/applying-slds/guidance/overviews/color.md +0 -266
  17. package/skills/applying-slds/guidance/overviews/display-density.md +0 -366
  18. package/skills/applying-slds/guidance/overviews/icons.md +0 -240
  19. package/skills/applying-slds/guidance/overviews/illustrations.md +0 -235
  20. package/skills/applying-slds/guidance/overviews/shadows.md +0 -176
  21. package/skills/applying-slds/guidance/overviews/spacing.md +0 -216
  22. package/skills/applying-slds/guidance/overviews/typography.md +0 -323
  23. package/skills/applying-slds/guidance/overviews/utilities.md +0 -542
  24. package/skills/applying-slds/guidance/slds-development-guide.md +0 -288
  25. package/skills/applying-slds/guidance/styling-hooks/borders.md +0 -202
  26. package/skills/applying-slds/guidance/styling-hooks/color/expressive-palette-hooks.md +0 -153
  27. package/skills/applying-slds/guidance/styling-hooks/color/index.md +0 -171
  28. package/skills/applying-slds/guidance/styling-hooks/color/semantic/accent-hooks.md +0 -204
  29. package/skills/applying-slds/guidance/styling-hooks/color/semantic/feedback-hooks.md +0 -768
  30. package/skills/applying-slds/guidance/styling-hooks/color/semantic/surface-hooks.md +0 -337
  31. package/skills/applying-slds/guidance/styling-hooks/color/system-hooks.md +0 -132
  32. package/skills/applying-slds/guidance/styling-hooks/index.md +0 -327
  33. package/skills/applying-slds/guidance/styling-hooks/shadows.md +0 -238
  34. package/skills/applying-slds/guidance/styling-hooks/spacing.md +0 -254
  35. package/skills/applying-slds/guidance/styling-hooks/typography.md +0 -448
  36. package/skills/applying-slds/guidance/utilities/alignment.md +0 -119
  37. package/skills/applying-slds/guidance/utilities/borders.md +0 -131
  38. package/skills/applying-slds/guidance/utilities/box.md +0 -125
  39. package/skills/applying-slds/guidance/utilities/color.md +0 -165
  40. package/skills/applying-slds/guidance/utilities/dark-mode.md +0 -111
  41. package/skills/applying-slds/guidance/utilities/description-list.md +0 -168
  42. package/skills/applying-slds/guidance/utilities/floats.md +0 -117
  43. package/skills/applying-slds/guidance/utilities/grid.md +0 -264
  44. package/skills/applying-slds/guidance/utilities/horizontal-list.md +0 -110
  45. package/skills/applying-slds/guidance/utilities/hyphenation.md +0 -84
  46. package/skills/applying-slds/guidance/utilities/index.md +0 -205
  47. package/skills/applying-slds/guidance/utilities/interactions.md +0 -89
  48. package/skills/applying-slds/guidance/utilities/layout.md +0 -109
  49. package/skills/applying-slds/guidance/utilities/line-clamp.md +0 -131
  50. package/skills/applying-slds/guidance/utilities/margin.md +0 -155
  51. package/skills/applying-slds/guidance/utilities/media-object.md +0 -161
  52. package/skills/applying-slds/guidance/utilities/name-value-list.md +0 -152
  53. package/skills/applying-slds/guidance/utilities/padding.md +0 -155
  54. package/skills/applying-slds/guidance/utilities/position.md +0 -177
  55. package/skills/applying-slds/guidance/utilities/print.md +0 -114
  56. package/skills/applying-slds/guidance/utilities/scrollable.md +0 -126
  57. package/skills/applying-slds/guidance/utilities/sizing.md +0 -190
  58. package/skills/applying-slds/guidance/utilities/themes.md +0 -121
  59. package/skills/applying-slds/guidance/utilities/truncate.md +0 -127
  60. package/skills/applying-slds/guidance/utilities/typography.md +0 -166
  61. package/skills/applying-slds/guidance/utilities/vertical-list.md +0 -166
  62. package/skills/applying-slds/guidance/utilities/visibility.md +0 -228
  63. package/skills/applying-slds/metadata/README.md +0 -84
  64. package/skills/applying-slds/metadata/blueprints/components/accordion.yaml +0 -304
  65. package/skills/applying-slds/metadata/blueprints/components/activity-timeline.yaml +0 -92
  66. package/skills/applying-slds/metadata/blueprints/components/alert.yaml +0 -103
  67. package/skills/applying-slds/metadata/blueprints/components/app-launcher.yaml +0 -94
  68. package/skills/applying-slds/metadata/blueprints/components/avatar-group.yaml +0 -81
  69. package/skills/applying-slds/metadata/blueprints/components/avatar.yaml +0 -97
  70. package/skills/applying-slds/metadata/blueprints/components/badges.yaml +0 -102
  71. package/skills/applying-slds/metadata/blueprints/components/brand-band.yaml +0 -198
  72. package/skills/applying-slds/metadata/blueprints/components/breadcrumbs.yaml +0 -95
  73. package/skills/applying-slds/metadata/blueprints/components/builder-header.yaml +0 -192
  74. package/skills/applying-slds/metadata/blueprints/components/button-groups.yaml +0 -82
  75. package/skills/applying-slds/metadata/blueprints/components/button-icons.yaml +0 -295
  76. package/skills/applying-slds/metadata/blueprints/components/buttons.yaml +0 -230
  77. package/skills/applying-slds/metadata/blueprints/components/cards.yaml +0 -124
  78. package/skills/applying-slds/metadata/blueprints/components/carousel.yaml +0 -140
  79. package/skills/applying-slds/metadata/blueprints/components/chat.yaml +0 -179
  80. package/skills/applying-slds/metadata/blueprints/components/checkbox-button-group.yaml +0 -192
  81. package/skills/applying-slds/metadata/blueprints/components/checkbox-button.yaml +0 -204
  82. package/skills/applying-slds/metadata/blueprints/components/checkbox-toggle.yaml +0 -177
  83. package/skills/applying-slds/metadata/blueprints/components/checkbox.yaml +0 -108
  84. package/skills/applying-slds/metadata/blueprints/components/color-picker.yaml +0 -172
  85. package/skills/applying-slds/metadata/blueprints/components/combobox.yaml +0 -136
  86. package/skills/applying-slds/metadata/blueprints/components/counter.yaml +0 -147
  87. package/skills/applying-slds/metadata/blueprints/components/data-tables.yaml +0 -157
  88. package/skills/applying-slds/metadata/blueprints/components/datepickers.yaml +0 -130
  89. package/skills/applying-slds/metadata/blueprints/components/datetime-picker.yaml +0 -155
  90. package/skills/applying-slds/metadata/blueprints/components/docked-composer.yaml +0 -201
  91. package/skills/applying-slds/metadata/blueprints/components/docked-form-footer.yaml +0 -161
  92. package/skills/applying-slds/metadata/blueprints/components/docked-utility-bar.yaml +0 -175
  93. package/skills/applying-slds/metadata/blueprints/components/drop-zone.yaml +0 -115
  94. package/skills/applying-slds/metadata/blueprints/components/dueling-picklist.yaml +0 -196
  95. package/skills/applying-slds/metadata/blueprints/components/dynamic-icons.yaml +0 -128
  96. package/skills/applying-slds/metadata/blueprints/components/dynamic-menu.yaml +0 -141
  97. package/skills/applying-slds/metadata/blueprints/components/expandable-section.yaml +0 -115
  98. package/skills/applying-slds/metadata/blueprints/components/expression.yaml +0 -143
  99. package/skills/applying-slds/metadata/blueprints/components/feeds.yaml +0 -125
  100. package/skills/applying-slds/metadata/blueprints/components/file-selector.yaml +0 -154
  101. package/skills/applying-slds/metadata/blueprints/components/files.yaml +0 -119
  102. package/skills/applying-slds/metadata/blueprints/components/form-element.yaml +0 -145
  103. package/skills/applying-slds/metadata/blueprints/components/global-header.yaml +0 -120
  104. package/skills/applying-slds/metadata/blueprints/components/global-navigation.yaml +0 -100
  105. package/skills/applying-slds/metadata/blueprints/components/icons.yaml +0 -138
  106. package/skills/applying-slds/metadata/blueprints/components/illustration.yaml +0 -205
  107. package/skills/applying-slds/metadata/blueprints/components/input.yaml +0 -151
  108. package/skills/applying-slds/metadata/blueprints/components/list-builder.yaml +0 -127
  109. package/skills/applying-slds/metadata/blueprints/components/lookups.yaml +0 -132
  110. package/skills/applying-slds/metadata/blueprints/components/map.yaml +0 -118
  111. package/skills/applying-slds/metadata/blueprints/components/menus.yaml +0 -134
  112. package/skills/applying-slds/metadata/blueprints/components/modals.yaml +0 -152
  113. package/skills/applying-slds/metadata/blueprints/components/notifications.yaml +0 -88
  114. package/skills/applying-slds/metadata/blueprints/components/page-headers.yaml +0 -135
  115. package/skills/applying-slds/metadata/blueprints/components/panels.yaml +0 -149
  116. package/skills/applying-slds/metadata/blueprints/components/path.yaml +0 -154
  117. package/skills/applying-slds/metadata/blueprints/components/picklist.yaml +0 -125
  118. package/skills/applying-slds/metadata/blueprints/components/pills.yaml +0 -154
  119. package/skills/applying-slds/metadata/blueprints/components/popovers.yaml +0 -120
  120. package/skills/applying-slds/metadata/blueprints/components/progress-bar.yaml +0 -110
  121. package/skills/applying-slds/metadata/blueprints/components/progress-indicator.yaml +0 -133
  122. package/skills/applying-slds/metadata/blueprints/components/progress-ring.yaml +0 -102
  123. package/skills/applying-slds/metadata/blueprints/components/prompt.yaml +0 -126
  124. package/skills/applying-slds/metadata/blueprints/components/publishers.yaml +0 -178
  125. package/skills/applying-slds/metadata/blueprints/components/radio-button-group.yaml +0 -172
  126. package/skills/applying-slds/metadata/blueprints/components/radio-group.yaml +0 -112
  127. package/skills/applying-slds/metadata/blueprints/components/rich-text-editor.yaml +0 -135
  128. package/skills/applying-slds/metadata/blueprints/components/scoped-notifications.yaml +0 -188
  129. package/skills/applying-slds/metadata/blueprints/components/scoped-tabs.yaml +0 -97
  130. package/skills/applying-slds/metadata/blueprints/components/select.yaml +0 -127
  131. package/skills/applying-slds/metadata/blueprints/components/setup-assistant.yaml +0 -152
  132. package/skills/applying-slds/metadata/blueprints/components/slider.yaml +0 -111
  133. package/skills/applying-slds/metadata/blueprints/components/spinners.yaml +0 -135
  134. package/skills/applying-slds/metadata/blueprints/components/split-view.yaml +0 -112
  135. package/skills/applying-slds/metadata/blueprints/components/summary-detail.yaml +0 -103
  136. package/skills/applying-slds/metadata/blueprints/components/tabs.yaml +0 -138
  137. package/skills/applying-slds/metadata/blueprints/components/textarea.yaml +0 -116
  138. package/skills/applying-slds/metadata/blueprints/components/tiles.yaml +0 -108
  139. package/skills/applying-slds/metadata/blueprints/components/timepicker.yaml +0 -111
  140. package/skills/applying-slds/metadata/blueprints/components/toast.yaml +0 -154
  141. package/skills/applying-slds/metadata/blueprints/components/tooltips.yaml +0 -107
  142. package/skills/applying-slds/metadata/blueprints/components/tree-grid.yaml +0 -116
  143. package/skills/applying-slds/metadata/blueprints/components/trees.yaml +0 -116
  144. package/skills/applying-slds/metadata/blueprints/components/trial-bar.yaml +0 -112
  145. package/skills/applying-slds/metadata/blueprints/components/vertical-navigation.yaml +0 -130
  146. package/skills/applying-slds/metadata/blueprints/components/vertical-tabs.yaml +0 -140
  147. package/skills/applying-slds/metadata/blueprints/components/visual-picker.yaml +0 -150
  148. package/skills/applying-slds/metadata/blueprints/components/welcome-mat.yaml +0 -136
  149. package/skills/applying-slds/metadata/hooks-index.json +0 -6272
  150. package/skills/applying-slds/metadata/icon-metadata.json +0 -38466
  151. package/skills/applying-slds/metadata/utilities-index.json +0 -21912
  152. package/skills/applying-slds/references/component-selection.md +0 -112
  153. package/skills/applying-slds/references/icons-decision-guide.md +0 -124
  154. package/skills/applying-slds/references/styling-decision-guide.md +0 -228
  155. package/skills/applying-slds/references/utilities-quick-ref.md +0 -125
  156. package/skills/applying-slds/scripts/search-blueprints.cjs +0 -117
  157. package/skills/applying-slds/scripts/search-hooks.cjs +0 -139
  158. package/skills/applying-slds/scripts/search-icons.cjs +0 -174
  159. package/skills/applying-slds/scripts/search-utilities.cjs +0 -161
  160. package/skills/building-mobile-apps/SKILL.md +0 -69
  161. package/skills/building-omnistudio-callable-apex/CREDITS.md +0 -9
  162. package/skills/building-omnistudio-callable-apex/README.md +0 -80
  163. package/skills/building-omnistudio-callable-apex/SKILL.md +0 -275
  164. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_openinterface.cls +0 -40
  165. package/skills/building-omnistudio-callable-apex/assets/pattern_callable_vanilla.cls +0 -32
  166. package/skills/building-omnistudio-callable-apex/assets/pattern_migration.cls +0 -54
  167. package/skills/building-omnistudio-callable-apex/assets/pattern_openinterface.cls +0 -45
  168. package/skills/building-omnistudio-callable-apex/assets/pattern_test_class.cls +0 -65
  169. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/IndustriesCallableException.cls +0 -7
  170. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.cls +0 -115
  171. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallableTest.cls +0 -189
  172. package/skills/building-omnistudio-callable-apex/examples/Test_QuoteByProductCallable/TRANSCRIPT.md +0 -115
  173. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.cls +0 -7
  174. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallable.cls +0 -74
  175. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomCallableTest.cls +0 -146
  176. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/MyCustomRemoteClass.cls +0 -16
  177. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md +0 -120
  178. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.cls +0 -7
  179. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallable.cls +0 -73
  180. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomCallableTest.cls +0 -128
  181. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/MyCustomVlocityOpenInterface2.cls +0 -23
  182. package/skills/building-omnistudio-callable-apex/examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md +0 -75
  183. package/skills/building-omnistudio-datamapper/CREDITS.md +0 -5
  184. package/skills/building-omnistudio-datamapper/SKILL.md +0 -269
  185. package/skills/building-omnistudio-datamapper/assets/completion-summary-template.md +0 -28
  186. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-extract.json +0 -6
  187. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-item.json +0 -12
  188. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-load.json +0 -6
  189. package/skills/building-omnistudio-datamapper/assets/omni-data-transform-transform.json +0 -6
  190. package/skills/building-omnistudio-datamapper/references/best-practices.md +0 -277
  191. package/skills/building-omnistudio-datamapper/references/naming-conventions.md +0 -145
  192. package/skills/building-omnistudio-flexcard/CREDITS.md +0 -5
  193. package/skills/building-omnistudio-flexcard/SKILL.md +0 -324
  194. package/skills/building-omnistudio-flexcard/assets/omni-ui-card.json +0 -10
  195. package/skills/building-omnistudio-flexcard/references/best-practices.md +0 -291
  196. package/skills/building-omnistudio-flexcard/references/data-binding-guide.md +0 -311
  197. package/skills/building-omnistudio-flexcard/references/scoring-rubric.md +0 -66
  198. package/skills/building-omnistudio-flexcard/scripts/flexcard-commands.sh +0 -24
  199. package/skills/building-omnistudio-integration-procedure/CREDITS.md +0 -5
  200. package/skills/building-omnistudio-integration-procedure/SKILL.md +0 -274
  201. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-dr-extract.json +0 -10
  202. package/skills/building-omnistudio-integration-procedure/assets/omni-process-element-set-values.json +0 -10
  203. package/skills/building-omnistudio-integration-procedure/assets/omni-process-ip.json +0 -12
  204. package/skills/building-omnistudio-integration-procedure/assets/scoring-report-format.txt +0 -14
  205. package/skills/building-omnistudio-integration-procedure/references/best-practices.md +0 -388
  206. package/skills/building-omnistudio-integration-procedure/references/element-types.md +0 -588
  207. package/skills/building-omnistudio-integration-procedure/scripts/cli-commands.sh +0 -18
  208. package/skills/building-omnistudio-omniscript/CREDITS.md +0 -5
  209. package/skills/building-omnistudio-omniscript/SKILL.md +0 -366
  210. package/skills/building-omnistudio-omniscript/assets/omni-process-element-step.json +0 -10
  211. package/skills/building-omnistudio-omniscript/assets/omni-process-element-text-block.json +0 -11
  212. package/skills/building-omnistudio-omniscript/assets/omni-process-omniscript.json +0 -12
  213. package/skills/building-omnistudio-omniscript/references/best-practices.md +0 -480
  214. package/skills/building-omnistudio-omniscript/references/element-types.md +0 -1172
  215. package/skills/building-omnistudio-omniscript/scripts/check-duplicate-omniscript.sh +0 -13
  216. package/skills/building-omnistudio-omniscript/scripts/cli-reference.sh +0 -21
  217. package/skills/building-omnistudio-omniscript/scripts/deploy-omniscript.sh +0 -29
  218. package/skills/building-sf-integrations/CREDITS.md +0 -5
  219. package/skills/building-sf-integrations/README.md +0 -95
  220. package/skills/building-sf-integrations/SKILL.md +0 -191
  221. package/skills/building-sf-integrations/assets/callouts/callout-retry-handler.cls +0 -167
  222. package/skills/building-sf-integrations/assets/callouts/http-response-handler.cls +0 -257
  223. package/skills/building-sf-integrations/assets/callouts/rest-queueable-callout.cls +0 -262
  224. package/skills/building-sf-integrations/assets/callouts/rest-sync-callout.cls +0 -211
  225. package/skills/building-sf-integrations/assets/cdc/cdc-handler.cls +0 -246
  226. package/skills/building-sf-integrations/assets/cdc/cdc-subscriber-trigger.trigger +0 -139
  227. package/skills/building-sf-integrations/assets/endpoint-security/example.cspTrustedSite-meta.xml +0 -58
  228. package/skills/building-sf-integrations/assets/endpoint-security/example.remoteSite-meta.xml +0 -39
  229. package/skills/building-sf-integrations/assets/external-credentials/jwt-external-credential.externalCredential-meta.xml +0 -90
  230. package/skills/building-sf-integrations/assets/external-credentials/oauth-external-credential.externalCredential-meta.xml +0 -87
  231. package/skills/building-sf-integrations/assets/external-services/external-service-operations.md +0 -221
  232. package/skills/building-sf-integrations/assets/external-services/openapi-registration.externalServiceRegistration-meta.xml +0 -193
  233. package/skills/building-sf-integrations/assets/named-credentials/certificate-auth.namedCredential-meta.xml +0 -62
  234. package/skills/building-sf-integrations/assets/named-credentials/custom-auth.namedCredential-meta.xml +0 -71
  235. package/skills/building-sf-integrations/assets/named-credentials/oauth-client-credentials.namedCredential-meta.xml +0 -51
  236. package/skills/building-sf-integrations/assets/named-credentials/oauth-jwt-bearer.namedCredential-meta.xml +0 -67
  237. package/skills/building-sf-integrations/assets/platform-events/event-publisher.cls +0 -191
  238. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-action.cls +0 -295
  239. package/skills/building-sf-integrations/assets/platform-events/event-subscriber-trigger.trigger +0 -108
  240. package/skills/building-sf-integrations/assets/platform-events/platform-event-definition.object-meta.xml +0 -124
  241. package/skills/building-sf-integrations/assets/soap/soap-callout-service.cls +0 -186
  242. package/skills/building-sf-integrations/assets/soap/wsdl2apex-guide.md +0 -213
  243. package/skills/building-sf-integrations/hooks/scripts/suggest_credential_setup.py +0 -271
  244. package/skills/building-sf-integrations/hooks/scripts/validate_integration.py +0 -363
  245. package/skills/building-sf-integrations/references/callout-patterns.md +0 -719
  246. package/skills/building-sf-integrations/references/cdc-guide.md +0 -288
  247. package/skills/building-sf-integrations/references/cli-reference.md +0 -94
  248. package/skills/building-sf-integrations/references/event-driven-architecture-guide.md +0 -266
  249. package/skills/building-sf-integrations/references/event-patterns.md +0 -838
  250. package/skills/building-sf-integrations/references/external-services-guide.md +0 -303
  251. package/skills/building-sf-integrations/references/messaging-api-v2.md +0 -609
  252. package/skills/building-sf-integrations/references/named-credentials-automation.md +0 -201
  253. package/skills/building-sf-integrations/references/named-credentials-guide.md +0 -173
  254. package/skills/building-sf-integrations/references/platform-events-guide.md +0 -288
  255. package/skills/building-sf-integrations/references/rest-callout-patterns.md +0 -288
  256. package/skills/building-sf-integrations/references/scoring-rubric.md +0 -59
  257. package/skills/building-sf-integrations/references/security-best-practices.md +0 -248
  258. package/skills/building-sf-integrations/scripts/README.md +0 -100
  259. package/skills/building-sf-integrations/scripts/configure-named-credential.sh +0 -236
  260. package/skills/building-sf-integrations/scripts/set-api-credential.sh +0 -146
  261. package/skills/building-sf-integrations/scripts/templates/setup-credentials-with-csp.sh +0 -158
  262. package/skills/building-ui-bundle-app/SKILL.md +0 -350
  263. package/skills/building-ui-bundle-frontend/SKILL.md +0 -135
  264. package/skills/building-ui-bundle-frontend/implementation/component.md +0 -78
  265. package/skills/building-ui-bundle-frontend/implementation/header-footer.md +0 -132
  266. package/skills/building-ui-bundle-frontend/implementation/page.md +0 -93
  267. package/skills/configuring-code-analyzer/SKILL.md +0 -482
  268. package/skills/configuring-code-analyzer/examples/apex-project-config.yml +0 -41
  269. package/skills/configuring-code-analyzer/examples/ci-github-actions.yml +0 -96
  270. package/skills/configuring-code-analyzer/examples/fullstack-project-config.yml +0 -46
  271. package/skills/configuring-code-analyzer/examples/lwc-project-config.yml +0 -26
  272. package/skills/configuring-code-analyzer/references/ci-cd-templates.md +0 -648
  273. package/skills/configuring-code-analyzer/references/config-schema.md +0 -257
  274. package/skills/configuring-code-analyzer/references/diagnostic-flow.md +0 -70
  275. package/skills/configuring-code-analyzer/references/engine-prerequisites.md +0 -276
  276. package/skills/configuring-code-analyzer/references/rule-name-resolution.md +0 -67
  277. package/skills/configuring-code-analyzer/references/troubleshooting.md +0 -298
  278. package/skills/configuring-code-analyzer/scripts/check-prerequisites.sh +0 -189
  279. package/skills/configuring-code-analyzer/scripts/generate-config.sh +0 -143
  280. package/skills/configuring-code-analyzer/scripts/validate-config.sh +0 -153
  281. package/skills/configuring-connected-apps/CREDITS.md +0 -3
  282. package/skills/configuring-connected-apps/README.md +0 -99
  283. package/skills/configuring-connected-apps/SKILL.md +0 -223
  284. package/skills/configuring-connected-apps/assets/connected-app-basic.xml +0 -29
  285. package/skills/configuring-connected-apps/assets/connected-app-canvas.xml +0 -62
  286. package/skills/configuring-connected-apps/assets/connected-app-jwt.xml +0 -49
  287. package/skills/configuring-connected-apps/assets/connected-app-oauth.xml +0 -65
  288. package/skills/configuring-connected-apps/assets/eca-global-oauth.xml +0 -36
  289. package/skills/configuring-connected-apps/assets/eca-oauth-settings.xml +0 -36
  290. package/skills/configuring-connected-apps/assets/eca-policies.xml +0 -36
  291. package/skills/configuring-connected-apps/assets/external-client-app.xml +0 -35
  292. package/skills/configuring-connected-apps/references/example-usage.md +0 -256
  293. package/skills/configuring-connected-apps/references/migration-guide.md +0 -328
  294. package/skills/configuring-connected-apps/references/oauth-flows-reference.md +0 -660
  295. package/skills/configuring-connected-apps/references/security-checklist.md +0 -209
  296. package/skills/configuring-connected-apps/references/testing-validation-guide.md +0 -275
  297. package/skills/connecting-datacloud/CREDITS.md +0 -5
  298. package/skills/connecting-datacloud/README.md +0 -59
  299. package/skills/connecting-datacloud/SKILL.md +0 -154
  300. package/skills/connecting-datacloud/examples/connections/heroku-postgres.json +0 -15
  301. package/skills/connecting-datacloud/examples/connections/ingest-api-connection.json +0 -5
  302. package/skills/connecting-datacloud/examples/connections/ingest-api-schema.json +0 -31
  303. package/skills/connecting-datacloud/examples/connections/redshift.json +0 -16
  304. package/skills/connecting-datacloud/examples/connections/sharepoint-unstructured.json +0 -20
  305. package/skills/connecting-datacloud/examples/connections/snowflake-connection.json +0 -42
  306. package/skills/creating-b2b-commerce-store/SKILL.md +0 -167
  307. package/skills/creating-b2b-commerce-store/references/store-vs-storefront.md +0 -169
  308. package/skills/debugging-apex-logs/CREDITS.md +0 -22
  309. package/skills/debugging-apex-logs/README.md +0 -74
  310. package/skills/debugging-apex-logs/SKILL.md +0 -171
  311. package/skills/debugging-apex-logs/assets/benchmarking-template.cls +0 -327
  312. package/skills/debugging-apex-logs/assets/cpu-heap-optimization.cls +0 -307
  313. package/skills/debugging-apex-logs/assets/dml-in-loop-fix.cls +0 -219
  314. package/skills/debugging-apex-logs/assets/null-pointer-fix.cls +0 -252
  315. package/skills/debugging-apex-logs/assets/soql-in-loop-fix.cls +0 -157
  316. package/skills/debugging-apex-logs/references/analysis-playbook.md +0 -53
  317. package/skills/debugging-apex-logs/references/benchmarking-guide.md +0 -287
  318. package/skills/debugging-apex-logs/references/cli-commands.md +0 -368
  319. package/skills/debugging-apex-logs/references/common-issues.md +0 -68
  320. package/skills/debugging-apex-logs/references/debug-log-reference.md +0 -328
  321. package/skills/debugging-apex-logs/references/log-analysis-tools.md +0 -248
  322. package/skills/debugging-apex-logs/references/scoring-rubric.md +0 -21
  323. package/skills/deploying-metadata/CREDITS.md +0 -25
  324. package/skills/deploying-metadata/README.md +0 -104
  325. package/skills/deploying-metadata/SKILL.md +0 -213
  326. package/skills/deploying-metadata/assets/destructiveChanges.xml +0 -143
  327. package/skills/deploying-metadata/assets/package.xml +0 -121
  328. package/skills/deploying-metadata/references/agent-deployment-guide.md +0 -628
  329. package/skills/deploying-metadata/references/deploy.sh +0 -73
  330. package/skills/deploying-metadata/references/deployment-report-template.md +0 -89
  331. package/skills/deploying-metadata/references/deployment-workflows.md +0 -395
  332. package/skills/deploying-metadata/references/orchestration.md +0 -183
  333. package/skills/deploying-metadata/references/trigger-deployment-safety.md +0 -376
  334. package/skills/deploying-omnistudio-datapacks/CREDITS.md +0 -5
  335. package/skills/deploying-omnistudio-datapacks/README.md +0 -88
  336. package/skills/deploying-omnistudio-datapacks/SKILL.md +0 -173
  337. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/TRANSCRIPT.md +0 -124
  338. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle/deploy-business-internet-plus-bundle.yaml +0 -11
  339. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/TRANSCRIPT.md +0 -142
  340. package/skills/deploying-omnistudio-datapacks/examples/business-internet-plus-bundle-deploy/deploy-business-internet-plus-bundle.yaml +0 -10
  341. package/skills/deploying-omnistudio-datapacks/references/job-file-template.md +0 -42
  342. package/skills/deploying-omnistudio-datapacks/references/troubleshooting-matrix.md +0 -24
  343. package/skills/deploying-ui-bundle/SKILL.md +0 -79
  344. package/skills/developing-agentforce/README.md +0 -112
  345. package/skills/developing-agentforce/SKILL.md +0 -518
  346. package/skills/developing-agentforce/assets/README-legacy.md +0 -89
  347. package/skills/developing-agentforce/assets/agent-spec-template.md +0 -90
  348. package/skills/developing-agentforce/assets/agents/README.md +0 -45
  349. package/skills/developing-agentforce/assets/agents/hello-world.agent +0 -60
  350. package/skills/developing-agentforce/assets/agents/multi-subagent.agent +0 -105
  351. package/skills/developing-agentforce/assets/agents/order-service.agent +0 -272
  352. package/skills/developing-agentforce/assets/agents/production-faq.agent +0 -101
  353. package/skills/developing-agentforce/assets/agents/production-faq.bundle-meta.xml +0 -4
  354. package/skills/developing-agentforce/assets/agents/simple-qa.agent +0 -72
  355. package/skills/developing-agentforce/assets/agents/verification-gate.agent +0 -280
  356. package/skills/developing-agentforce/assets/apex/models-api-queueable.cls +0 -225
  357. package/skills/developing-agentforce/assets/bundle-meta.xml +0 -23
  358. package/skills/developing-agentforce/assets/components/apex-action.agent +0 -52
  359. package/skills/developing-agentforce/assets/components/error-handling.agent +0 -58
  360. package/skills/developing-agentforce/assets/components/escalation-setup.agent +0 -169
  361. package/skills/developing-agentforce/assets/components/flow-action.agent +0 -66
  362. package/skills/developing-agentforce/assets/components/n-ary-conditions.agent +0 -110
  363. package/skills/developing-agentforce/assets/components/subagent-with-actions.agent +0 -40
  364. package/skills/developing-agentforce/assets/deterministic-routing.agent +0 -166
  365. package/skills/developing-agentforce/assets/escalation-pattern.agent +0 -209
  366. package/skills/developing-agentforce/assets/flow-action-lookup.agent +0 -115
  367. package/skills/developing-agentforce/assets/hub-and-spoke.agent +0 -104
  368. package/skills/developing-agentforce/assets/invocable-apex-template.cls +0 -187
  369. package/skills/developing-agentforce/assets/local-info-agent-annotated.agent +0 -355
  370. package/skills/developing-agentforce/assets/metadata/basic-prompt-template.promptTemplate-meta.xml +0 -109
  371. package/skills/developing-agentforce/assets/metadata/genai-function-apex.xml +0 -92
  372. package/skills/developing-agentforce/assets/metadata/genai-function-flow.xml +0 -57
  373. package/skills/developing-agentforce/assets/metadata/genai-plugin.xml +0 -72
  374. package/skills/developing-agentforce/assets/metadata/http-callout-flow.flow-meta.xml +0 -348
  375. package/skills/developing-agentforce/assets/metadata/record-grounded-prompt.promptTemplate-meta.xml +0 -136
  376. package/skills/developing-agentforce/assets/minimal-starter.agent +0 -42
  377. package/skills/developing-agentforce/assets/patterns/README.md +0 -254
  378. package/skills/developing-agentforce/assets/patterns/action-callbacks.agent +0 -178
  379. package/skills/developing-agentforce/assets/patterns/advanced-input-bindings.agent +0 -141
  380. package/skills/developing-agentforce/assets/patterns/bidirectional-routing.agent +0 -156
  381. package/skills/developing-agentforce/assets/patterns/critical-input-collection.agent +0 -244
  382. package/skills/developing-agentforce/assets/patterns/delegation-routing.agent +0 -89
  383. package/skills/developing-agentforce/assets/patterns/lifecycle-events.agent +0 -127
  384. package/skills/developing-agentforce/assets/patterns/llm-controlled-actions.agent +0 -184
  385. package/skills/developing-agentforce/assets/patterns/multi-step-workflow.agent +0 -282
  386. package/skills/developing-agentforce/assets/patterns/open-gate-routing.agent +0 -287
  387. package/skills/developing-agentforce/assets/patterns/procedural-instructions.agent +0 -273
  388. package/skills/developing-agentforce/assets/patterns/prompt-template-action.agent +0 -188
  389. package/skills/developing-agentforce/assets/patterns/system-instruction-overrides.agent +0 -293
  390. package/skills/developing-agentforce/assets/prompt-rag-search.agent +0 -131
  391. package/skills/developing-agentforce/assets/template-multi-subagent.agent +0 -160
  392. package/skills/developing-agentforce/assets/template-single-subagent.agent +0 -81
  393. package/skills/developing-agentforce/assets/verification-gate.agent +0 -208
  394. package/skills/developing-agentforce/references/action-prompt-templates.md +0 -164
  395. package/skills/developing-agentforce/references/actions-reference.md +0 -612
  396. package/skills/developing-agentforce/references/agent-access-guide.md +0 -72
  397. package/skills/developing-agentforce/references/agent-design-and-spec-creation.md +0 -1010
  398. package/skills/developing-agentforce/references/agent-metadata-and-lifecycle.md +0 -575
  399. package/skills/developing-agentforce/references/agent-script-core-language.md +0 -1255
  400. package/skills/developing-agentforce/references/agent-subagent-map-diagrams.md +0 -323
  401. package/skills/developing-agentforce/references/agent-user-setup.md +0 -529
  402. package/skills/developing-agentforce/references/agent-validation-and-debugging.md +0 -805
  403. package/skills/developing-agentforce/references/architecture-patterns.md +0 -158
  404. package/skills/developing-agentforce/references/complex-data-types.md +0 -57
  405. package/skills/developing-agentforce/references/deploy-reference.md +0 -134
  406. package/skills/developing-agentforce/references/discover-reference.md +0 -102
  407. package/skills/developing-agentforce/references/examples.md +0 -350
  408. package/skills/developing-agentforce/references/feature-validity.md +0 -43
  409. package/skills/developing-agentforce/references/instruction-resolution.md +0 -545
  410. package/skills/developing-agentforce/references/known-issues.md +0 -353
  411. package/skills/developing-agentforce/references/minimal-examples.md +0 -67
  412. package/skills/developing-agentforce/references/production-gotchas.md +0 -300
  413. package/skills/developing-agentforce/references/safety-review-reference.md +0 -145
  414. package/skills/developing-agentforce/references/salesforce-cli-for-agents.md +0 -395
  415. package/skills/developing-agentforce/references/scaffold-reference.md +0 -153
  416. package/skills/developing-agentforce/references/scoring-rubric.md +0 -24
  417. package/skills/developing-agentforce/references/version-history.md +0 -23
  418. package/skills/dx-app-analytics-use/SKILL.md +0 -135
  419. package/skills/fetching-salesforce-docs/README.md +0 -66
  420. package/skills/fetching-salesforce-docs/SKILL.md +0 -208
  421. package/skills/fetching-salesforce-docs/requirements.txt +0 -2
  422. package/skills/fetching-salesforce-docs/scripts/extract_help_salesforce.py +0 -497
  423. package/skills/fetching-salesforce-docs/scripts/extract_salesforce_doc.py +0 -357
  424. package/skills/fetching-salesforce-docs/scripts/runtime_bootstrap.py +0 -58
  425. package/skills/generating-apex/CREDITS.md +0 -5
  426. package/skills/generating-apex/SKILL.md +0 -409
  427. package/skills/generating-apex/assets/abstract.cls +0 -131
  428. package/skills/generating-apex/assets/batch.cls +0 -124
  429. package/skills/generating-apex/assets/domain.cls +0 -101
  430. package/skills/generating-apex/assets/dto.cls +0 -107
  431. package/skills/generating-apex/assets/exception.cls +0 -50
  432. package/skills/generating-apex/assets/interface.cls +0 -24
  433. package/skills/generating-apex/assets/invocable.cls +0 -114
  434. package/skills/generating-apex/assets/queueable.cls +0 -91
  435. package/skills/generating-apex/assets/rest-resource.cls +0 -300
  436. package/skills/generating-apex/assets/schedulable.cls +0 -74
  437. package/skills/generating-apex/assets/selector.cls +0 -91
  438. package/skills/generating-apex/assets/service.cls +0 -68
  439. package/skills/generating-apex/assets/trigger.cls +0 -45
  440. package/skills/generating-apex/assets/utility.cls +0 -96
  441. package/skills/generating-apex/references/AccountDeduplicationBatch.cls +0 -147
  442. package/skills/generating-apex/references/AccountSelector.cls +0 -192
  443. package/skills/generating-apex/references/AccountService.cls +0 -200
  444. package/skills/generating-apex-test/CREDITS.md +0 -5
  445. package/skills/generating-apex-test/SKILL.md +0 -201
  446. package/skills/generating-apex-test/assets/test-class-template.cls +0 -93
  447. package/skills/generating-apex-test/assets/test-data-factory-template.cls +0 -111
  448. package/skills/generating-apex-test/references/assertion-patterns.md +0 -108
  449. package/skills/generating-apex-test/references/async-testing.md +0 -193
  450. package/skills/generating-apex-test/references/mocking-patterns.md +0 -220
  451. package/skills/generating-apex-test/references/test-data-factory.md +0 -75
  452. package/skills/generating-custom-application/SKILL.md +0 -211
  453. package/skills/generating-custom-field/SKILL.md +0 -503
  454. package/skills/generating-custom-lightning-type/SKILL.md +0 -180
  455. package/skills/generating-custom-lightning-type/assets/primitive-types-and-constraints.md +0 -41
  456. package/skills/generating-custom-lightning-type/references/widget-rendition.md +0 -124
  457. package/skills/generating-custom-object/SKILL.md +0 -240
  458. package/skills/generating-custom-tab/SKILL.md +0 -156
  459. package/skills/generating-flexipage/SKILL.md +0 -522
  460. package/skills/generating-flow/SKILL.md +0 -372
  461. package/skills/generating-lightning-app/SKILL.md +0 -423
  462. package/skills/generating-list-view/SKILL.md +0 -218
  463. package/skills/generating-lwc-components/CREDITS.md +0 -5
  464. package/skills/generating-lwc-components/README.md +0 -126
  465. package/skills/generating-lwc-components/SKILL.md +0 -190
  466. package/skills/generating-lwc-components/assets/apex-controller/LwcController.cls +0 -327
  467. package/skills/generating-lwc-components/assets/basic-component/basicComponent.css +0 -72
  468. package/skills/generating-lwc-components/assets/basic-component/basicComponent.html +0 -111
  469. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js +0 -163
  470. package/skills/generating-lwc-components/assets/basic-component/basicComponent.js-meta.xml +0 -137
  471. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.html +0 -111
  472. package/skills/generating-lwc-components/assets/datatable-component/datatableComponent.js +0 -367
  473. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.css +0 -63
  474. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.html +0 -154
  475. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js +0 -348
  476. package/skills/generating-lwc-components/assets/flow-screen-component/flowScreenComponent.js-meta.xml +0 -87
  477. package/skills/generating-lwc-components/assets/form-component/formComponent.html +0 -165
  478. package/skills/generating-lwc-components/assets/form-component/formComponent.js +0 -275
  479. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.html +0 -100
  480. package/skills/generating-lwc-components/assets/graphql-component/graphqlComponent.js +0 -336
  481. package/skills/generating-lwc-components/assets/jest-test/componentName.test.js.example +0 -371
  482. package/skills/generating-lwc-components/assets/message-channel/RecordSelected.messageChannel-meta.xml +0 -71
  483. package/skills/generating-lwc-components/assets/message-channel/lmsPublisher.js +0 -103
  484. package/skills/generating-lwc-components/assets/message-channel/lmsSubscriber.js +0 -181
  485. package/skills/generating-lwc-components/assets/modal-component/modalComponent.html +0 -85
  486. package/skills/generating-lwc-components/assets/modal-component/modalComponent.js +0 -199
  487. package/skills/generating-lwc-components/assets/record-picker/recordPicker.html +0 -55
  488. package/skills/generating-lwc-components/assets/record-picker/recordPicker.js +0 -199
  489. package/skills/generating-lwc-components/assets/state-store/store.js +0 -282
  490. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.css +0 -65
  491. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.html +0 -95
  492. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.js-meta.xml +0 -75
  493. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.test.ts.example +0 -301
  494. package/skills/generating-lwc-components/assets/typescript-component/typescriptComponent.ts +0 -295
  495. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.html +0 -71
  496. package/skills/generating-lwc-components/assets/workspace-api/workspaceComponent.js +0 -316
  497. package/skills/generating-lwc-components/hooks/scripts/lwc-lsp-validate.py +0 -295
  498. package/skills/generating-lwc-components/hooks/scripts/post-tool-validate.py +0 -347
  499. package/skills/generating-lwc-components/hooks/scripts/slds_data/deprecated_patterns.json +0 -74
  500. package/skills/generating-lwc-components/hooks/scripts/slds_data/styling_hooks.json +0 -111
  501. package/skills/generating-lwc-components/hooks/scripts/slds_data/valid_slds_classes.json +0 -127
  502. package/skills/generating-lwc-components/hooks/scripts/slds_linter_wrapper.py +0 -294
  503. package/skills/generating-lwc-components/hooks/scripts/slds_rules/__init__.py +0 -22
  504. package/skills/generating-lwc-components/hooks/scripts/template_validator.py +0 -332
  505. package/skills/generating-lwc-components/hooks/scripts/validate_slds.py +0 -595
  506. package/skills/generating-lwc-components/references/accessibility-guide.md +0 -843
  507. package/skills/generating-lwc-components/references/advanced-features.md +0 -108
  508. package/skills/generating-lwc-components/references/async-notification-patterns.md +0 -661
  509. package/skills/generating-lwc-components/references/cli-commands.md +0 -545
  510. package/skills/generating-lwc-components/references/component-patterns.md +0 -1476
  511. package/skills/generating-lwc-components/references/flow-integration-guide.md +0 -675
  512. package/skills/generating-lwc-components/references/jest-testing.md +0 -1011
  513. package/skills/generating-lwc-components/references/lms-guide.md +0 -860
  514. package/skills/generating-lwc-components/references/lwc-best-practices.md +0 -1310
  515. package/skills/generating-lwc-components/references/performance-guide.md +0 -861
  516. package/skills/generating-lwc-components/references/scoring-and-testing.md +0 -116
  517. package/skills/generating-lwc-components/references/slds-blueprints.json +0 -14389
  518. package/skills/generating-lwc-components/references/slds-design-guide.md +0 -166
  519. package/skills/generating-lwc-components/references/state-management.md +0 -642
  520. package/skills/generating-lwc-components/references/template-anti-patterns.md +0 -948
  521. package/skills/generating-lwc-components/references/triangle-pattern.md +0 -365
  522. package/skills/generating-lwc-components/scripts/local-dev-preview.sh +0 -34
  523. package/skills/generating-mermaid-diagrams/CREDITS.md +0 -46
  524. package/skills/generating-mermaid-diagrams/README.md +0 -114
  525. package/skills/generating-mermaid-diagrams/SKILL.md +0 -217
  526. package/skills/generating-mermaid-diagrams/assets/agentforce/agent-flow.md +0 -313
  527. package/skills/generating-mermaid-diagrams/assets/architecture/system-landscape.md +0 -351
  528. package/skills/generating-mermaid-diagrams/assets/datamodel/b2b-commerce-erd.md +0 -317
  529. package/skills/generating-mermaid-diagrams/assets/datamodel/campaigns-erd.md +0 -195
  530. package/skills/generating-mermaid-diagrams/assets/datamodel/consent-erd.md +0 -262
  531. package/skills/generating-mermaid-diagrams/assets/datamodel/files-erd.md +0 -266
  532. package/skills/generating-mermaid-diagrams/assets/datamodel/forecasting-erd.md +0 -261
  533. package/skills/generating-mermaid-diagrams/assets/datamodel/fsl-erd.md +0 -332
  534. package/skills/generating-mermaid-diagrams/assets/datamodel/party-model-erd.md +0 -237
  535. package/skills/generating-mermaid-diagrams/assets/datamodel/quote-order-erd.md +0 -277
  536. package/skills/generating-mermaid-diagrams/assets/datamodel/revenue-cloud-erd.md +0 -343
  537. package/skills/generating-mermaid-diagrams/assets/datamodel/sales-cloud-erd.md +0 -192
  538. package/skills/generating-mermaid-diagrams/assets/datamodel/salesforce-erd.md +0 -209
  539. package/skills/generating-mermaid-diagrams/assets/datamodel/scheduler-erd.md +0 -276
  540. package/skills/generating-mermaid-diagrams/assets/datamodel/service-cloud-erd.md +0 -217
  541. package/skills/generating-mermaid-diagrams/assets/datamodel/territory-management-erd.md +0 -241
  542. package/skills/generating-mermaid-diagrams/assets/integration/api-sequence.md +0 -387
  543. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code-pkce.md +0 -197
  544. package/skills/generating-mermaid-diagrams/assets/oauth/authorization-code.md +0 -152
  545. package/skills/generating-mermaid-diagrams/assets/oauth/client-credentials.md +0 -233
  546. package/skills/generating-mermaid-diagrams/assets/oauth/device-authorization.md +0 -295
  547. package/skills/generating-mermaid-diagrams/assets/oauth/jwt-bearer.md +0 -256
  548. package/skills/generating-mermaid-diagrams/assets/oauth/refresh-token.md +0 -281
  549. package/skills/generating-mermaid-diagrams/assets/oauth/user-agent-social-sign-on.md +0 -281
  550. package/skills/generating-mermaid-diagrams/assets/role-hierarchy/user-hierarchy.md +0 -322
  551. package/skills/generating-mermaid-diagrams/references/color-palette.md +0 -464
  552. package/skills/generating-mermaid-diagrams/references/diagram-conventions.md +0 -313
  553. package/skills/generating-mermaid-diagrams/references/erd-conventions.md +0 -320
  554. package/skills/generating-mermaid-diagrams/references/mermaid-reference.md +0 -434
  555. package/skills/generating-mermaid-diagrams/references/mermaid-styling.md +0 -81
  556. package/skills/generating-mermaid-diagrams/references/preview-guide.md +0 -46
  557. package/skills/generating-mermaid-diagrams/references/usage-examples.md +0 -340
  558. package/skills/generating-mermaid-diagrams/scripts/README.md +0 -160
  559. package/skills/generating-mermaid-diagrams/scripts/mermaid_preview.py +0 -654
  560. package/skills/generating-mermaid-diagrams/scripts/query-org-metadata.py +0 -293
  561. package/skills/generating-permission-set/SKILL.md +0 -189
  562. package/skills/generating-ui-bundle-custom-app/SKILL.md +0 -93
  563. package/skills/generating-ui-bundle-custom-app/docs/configure-metadata-custom-application.md +0 -70
  564. package/skills/generating-ui-bundle-features/SKILL.md +0 -47
  565. package/skills/generating-ui-bundle-metadata/SKILL.md +0 -153
  566. package/skills/generating-ui-bundle-metadata/implementation/csp-metadata-format.md +0 -281
  567. package/skills/generating-ui-bundle-site/SKILL.md +0 -92
  568. package/skills/generating-ui-bundle-site/docs/configure-metadata-custom-site.md +0 -41
  569. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience-bundle.md +0 -17
  570. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience-config.md +0 -21
  571. package/skills/generating-ui-bundle-site/docs/configure-metadata-digital-experience.md +0 -40
  572. package/skills/generating-ui-bundle-site/docs/configure-metadata-network.md +0 -72
  573. package/skills/generating-ui-bundle-site/docs/update-site-urls.md +0 -100
  574. package/skills/generating-validation-rule/SKILL.md +0 -74
  575. package/skills/generating-visual-diagrams/CREDITS.md +0 -80
  576. package/skills/generating-visual-diagrams/README.md +0 -83
  577. package/skills/generating-visual-diagrams/SKILL.md +0 -207
  578. package/skills/generating-visual-diagrams/assets/architecture/integration-flow.md +0 -55
  579. package/skills/generating-visual-diagrams/assets/erd/core-objects.md +0 -131
  580. package/skills/generating-visual-diagrams/assets/erd/custom-objects.md +0 -60
  581. package/skills/generating-visual-diagrams/assets/lwc/dashboard-card.md +0 -45
  582. package/skills/generating-visual-diagrams/assets/lwc/data-table.md +0 -57
  583. package/skills/generating-visual-diagrams/assets/lwc/record-form.md +0 -60
  584. package/skills/generating-visual-diagrams/assets/review/apex-review.md +0 -57
  585. package/skills/generating-visual-diagrams/assets/review/lwc-review.md +0 -48
  586. package/skills/generating-visual-diagrams/references/architect-aesthetic-guide.md +0 -257
  587. package/skills/generating-visual-diagrams/references/examples-index.md +0 -35
  588. package/skills/generating-visual-diagrams/references/gemini-cli-setup.md +0 -65
  589. package/skills/generating-visual-diagrams/references/interview-questions.md +0 -529
  590. package/skills/generating-visual-diagrams/references/iteration-workflow.md +0 -173
  591. package/skills/generating-visual-diagrams/scripts/check-prerequisites.sh +0 -101
  592. package/skills/generating-visual-diagrams/scripts/generate_image.py +0 -243
  593. package/skills/getting-metadata-api-context/README.md +0 -79
  594. package/skills/getting-metadata-api-context/SKILL.md +0 -466
  595. package/skills/getting-metadata-api-context/data/metadata_api/AIApplication.json +0 -37
  596. package/skills/getting-metadata-api-context/data/metadata_api/AIApplicationConfig.json +0 -53
  597. package/skills/getting-metadata-api-context/data/metadata_api/AIReplyRecommendationsSettings.json +0 -40
  598. package/skills/getting-metadata-api-context/data/metadata_api/AIScoringModelDefinition.json +0 -87
  599. package/skills/getting-metadata-api-context/data/metadata_api/AIUsecaseDefinition.json +0 -215
  600. package/skills/getting-metadata-api-context/data/metadata_api/AccountInsightsSettings.json +0 -30
  601. package/skills/getting-metadata-api-context/data/metadata_api/AccountIntelligenceSettings.json +0 -40
  602. package/skills/getting-metadata-api-context/data/metadata_api/AccountPlanObjMeasCalcDef.json +0 -86
  603. package/skills/getting-metadata-api-context/data/metadata_api/AccountPlanSettings.json +0 -32
  604. package/skills/getting-metadata-api-context/data/metadata_api/AccountRelationshipShareRule.json +0 -56
  605. package/skills/getting-metadata-api-context/data/metadata_api/AccountSettings.json +0 -64
  606. package/skills/getting-metadata-api-context/data/metadata_api/AccountingFieldMapping.json +0 -70
  607. package/skills/getting-metadata-api-context/data/metadata_api/AccountingModelConfig.json +0 -94
  608. package/skills/getting-metadata-api-context/data/metadata_api/AccountingSettings.json +0 -53
  609. package/skills/getting-metadata-api-context/data/metadata_api/ActionLinkGroupTemplate.json +0 -118
  610. package/skills/getting-metadata-api-context/data/metadata_api/ActionOverride.json +0 -70
  611. package/skills/getting-metadata-api-context/data/metadata_api/ActionPlanTemplate.json +0 -166
  612. package/skills/getting-metadata-api-context/data/metadata_api/ActionableListDefinition.json +0 -114
  613. package/skills/getting-metadata-api-context/data/metadata_api/ActionsSettings.json +0 -44
  614. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatform.json +0 -95
  615. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatformActvAttr.json +0 -8
  616. package/skills/getting-metadata-api-context/data/metadata_api/ActivationPlatformField.json +0 -55
  617. package/skills/getting-metadata-api-context/data/metadata_api/ActivitiesSettings.json +0 -136
  618. package/skills/getting-metadata-api-context/data/metadata_api/ActvPfrmDataConnectorS3.json +0 -41
  619. package/skills/getting-metadata-api-context/data/metadata_api/ActvPlatformAdncIdentifier.json +0 -46
  620. package/skills/getting-metadata-api-context/data/metadata_api/ActvPlatformFieldValue.json +0 -50
  621. package/skills/getting-metadata-api-context/data/metadata_api/AddressSettings.json +0 -90
  622. package/skills/getting-metadata-api-context/data/metadata_api/AdvAccountForecastSet.json +0 -261
  623. package/skills/getting-metadata-api-context/data/metadata_api/AffinityScoreDefinition.json +0 -74
  624. package/skills/getting-metadata-api-context/data/metadata_api/AgentPlatformSettings.json +0 -32
  625. package/skills/getting-metadata-api-context/data/metadata_api/AgentforceForDevelopersSettings.json +0 -32
  626. package/skills/getting-metadata-api-context/data/metadata_api/AiAuthoringBundle.json +0 -44
  627. package/skills/getting-metadata-api-context/data/metadata_api/AiEvaluationDefinition.json +0 -153
  628. package/skills/getting-metadata-api-context/data/metadata_api/AiPluginUtteranceDef.json +0 -40
  629. package/skills/getting-metadata-api-context/data/metadata_api/AllOrNoneHeader.json +0 -17
  630. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticSnapshot.json +0 -80
  631. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsDashboard.json +0 -369
  632. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsSettings.json +0 -488
  633. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsVisualization.json +0 -180
  634. package/skills/getting-metadata-api-context/data/metadata_api/AnalyticsWorkspace.json +0 -71
  635. package/skills/getting-metadata-api-context/data/metadata_api/AnimationRule.json +0 -71
  636. package/skills/getting-metadata-api-context/data/metadata_api/ApexClass.json +0 -70
  637. package/skills/getting-metadata-api-context/data/metadata_api/ApexComponent.json +0 -44
  638. package/skills/getting-metadata-api-context/data/metadata_api/ApexEmailNotifications.json +0 -49
  639. package/skills/getting-metadata-api-context/data/metadata_api/ApexPage.json +0 -64
  640. package/skills/getting-metadata-api-context/data/metadata_api/ApexSettings.json +0 -96
  641. package/skills/getting-metadata-api-context/data/metadata_api/ApexTestSuite.json +0 -32
  642. package/skills/getting-metadata-api-context/data/metadata_api/ApexTrigger.json +0 -52
  643. package/skills/getting-metadata-api-context/data/metadata_api/AppAnalyticsSettings.json +0 -36
  644. package/skills/getting-metadata-api-context/data/metadata_api/AppExperienceSettings.json +0 -32
  645. package/skills/getting-metadata-api-context/data/metadata_api/AppFrameworkTemplateBundle.json +0 -52
  646. package/skills/getting-metadata-api-context/data/metadata_api/AppMenu.json +0 -10
  647. package/skills/getting-metadata-api-context/data/metadata_api/AppointmentAssignmentPolicy.json +0 -48
  648. package/skills/getting-metadata-api-context/data/metadata_api/AppointmentSchedulingPolicy.json +0 -102
  649. package/skills/getting-metadata-api-context/data/metadata_api/ApprovalProcess.json +0 -234
  650. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType.json +0 -81
  651. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType_CustomField.json +0 -88
  652. package/skills/getting-metadata-api-context/data/metadata_api/ArticleType_Layout.json +0 -63
  653. package/skills/getting-metadata-api-context/data/metadata_api/AssessmentQuestion.json +0 -117
  654. package/skills/getting-metadata-api-context/data/metadata_api/AssessmentQuestionSet.json +0 -41
  655. package/skills/getting-metadata-api-context/data/metadata_api/AssignmentRules.json +0 -87
  656. package/skills/getting-metadata-api-context/data/metadata_api/AssociationEngineSettings.json +0 -32
  657. package/skills/getting-metadata-api-context/data/metadata_api/AsyncResult.json +0 -89
  658. package/skills/getting-metadata-api-context/data/metadata_api/Audience.json +0 -172
  659. package/skills/getting-metadata-api-context/data/metadata_api/AuraDefinitionBundle.json +0 -94
  660. package/skills/getting-metadata-api-context/data/metadata_api/AuthProvider.json +0 -169
  661. package/skills/getting-metadata-api-context/data/metadata_api/AutoResponseRules.json +0 -79
  662. package/skills/getting-metadata-api-context/data/metadata_api/AutomatedContactsSettings.json +0 -44
  663. package/skills/getting-metadata-api-context/data/metadata_api/BaseSharingRule.json +0 -24
  664. package/skills/getting-metadata-api-context/data/metadata_api/BatchCalcJobDefinition.json +0 -849
  665. package/skills/getting-metadata-api-context/data/metadata_api/BatchProcessJobDefinition.json +0 -175
  666. package/skills/getting-metadata-api-context/data/metadata_api/BillingSettings.json +0 -152
  667. package/skills/getting-metadata-api-context/data/metadata_api/BlacklistedConsumer.json +0 -47
  668. package/skills/getting-metadata-api-context/data/metadata_api/Bot.json +0 -197
  669. package/skills/getting-metadata-api-context/data/metadata_api/BotBlock.json +0 -86
  670. package/skills/getting-metadata-api-context/data/metadata_api/BotSettings.json +0 -32
  671. package/skills/getting-metadata-api-context/data/metadata_api/BotTemplate.json +0 -96
  672. package/skills/getting-metadata-api-context/data/metadata_api/BotVersion.json +0 -667
  673. package/skills/getting-metadata-api-context/data/metadata_api/BranchManagementSettings.json +0 -32
  674. package/skills/getting-metadata-api-context/data/metadata_api/BrandingSet.json +0 -146
  675. package/skills/getting-metadata-api-context/data/metadata_api/BriefcaseDefinition.json +0 -127
  676. package/skills/getting-metadata-api-context/data/metadata_api/BusinessHoursSettings.json +0 -175
  677. package/skills/getting-metadata-api-context/data/metadata_api/BusinessProcess.json +0 -47
  678. package/skills/getting-metadata-api-context/data/metadata_api/BusinessProcessGroup.json +0 -91
  679. package/skills/getting-metadata-api-context/data/metadata_api/CMSConnectSource.json +0 -197
  680. package/skills/getting-metadata-api-context/data/metadata_api/CallCenter.json +0 -124
  681. package/skills/getting-metadata-api-context/data/metadata_api/CallCenterRoutingMap.json +0 -58
  682. package/skills/getting-metadata-api-context/data/metadata_api/CallCoachingMediaProvider.json +0 -40
  683. package/skills/getting-metadata-api-context/data/metadata_api/CallOptions.json +0 -17
  684. package/skills/getting-metadata-api-context/data/metadata_api/CampaignInfluenceModel.json +0 -59
  685. package/skills/getting-metadata-api-context/data/metadata_api/CampaignSettings.json +0 -71
  686. package/skills/getting-metadata-api-context/data/metadata_api/CancelDeployResult.json +0 -10
  687. package/skills/getting-metadata-api-context/data/metadata_api/CareBenefitVerifySettings.json +0 -70
  688. package/skills/getting-metadata-api-context/data/metadata_api/CareLimitType.json +0 -46
  689. package/skills/getting-metadata-api-context/data/metadata_api/CareProviderSearchConfig.json +0 -54
  690. package/skills/getting-metadata-api-context/data/metadata_api/CareRequestConfiguration.json +0 -57
  691. package/skills/getting-metadata-api-context/data/metadata_api/CareSystemFieldMapping.json +0 -58
  692. package/skills/getting-metadata-api-context/data/metadata_api/CaseSettings.json +0 -423
  693. package/skills/getting-metadata-api-context/data/metadata_api/CaseSubjectParticle.json +0 -35
  694. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApi.json +0 -97
  695. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApiArtifactVersionInfo.json +0 -46
  696. package/skills/getting-metadata-api-context/data/metadata_api/CatalogedApiVersion.json +0 -51
  697. package/skills/getting-metadata-api-context/data/metadata_api/Certificate.json +0 -54
  698. package/skills/getting-metadata-api-context/data/metadata_api/ChannelLayout.json +0 -63
  699. package/skills/getting-metadata-api-context/data/metadata_api/ChatterAnswersSettings.json +0 -76
  700. package/skills/getting-metadata-api-context/data/metadata_api/ChatterEmailsMDSettings.json +0 -68
  701. package/skills/getting-metadata-api-context/data/metadata_api/ChatterExtension.json +0 -64
  702. package/skills/getting-metadata-api-context/data/metadata_api/ChatterSettings.json +0 -92
  703. package/skills/getting-metadata-api-context/data/metadata_api/ChoiceList.json +0 -66
  704. package/skills/getting-metadata-api-context/data/metadata_api/ClaimFinancialSettings.json +0 -51
  705. package/skills/getting-metadata-api-context/data/metadata_api/ClauseCatgConfiguration.json +0 -45
  706. package/skills/getting-metadata-api-context/data/metadata_api/CleanDataService.json +0 -166
  707. package/skills/getting-metadata-api-context/data/metadata_api/CodeBuilderSettings.json +0 -32
  708. package/skills/getting-metadata-api-context/data/metadata_api/CollectionsDashboardSettings.json +0 -32
  709. package/skills/getting-metadata-api-context/data/metadata_api/CommerceSettings.json +0 -80
  710. package/skills/getting-metadata-api-context/data/metadata_api/CommunitiesSettings.json +0 -116
  711. package/skills/getting-metadata-api-context/data/metadata_api/Community.json +0 -121
  712. package/skills/getting-metadata-api-context/data/metadata_api/CommunityTemplateDefinition.json +0 -116
  713. package/skills/getting-metadata-api-context/data/metadata_api/CommunityThemeDefinition.json +0 -146
  714. package/skills/getting-metadata-api-context/data/metadata_api/CompactLayout.json +0 -32
  715. package/skills/getting-metadata-api-context/data/metadata_api/CompanySettings.json +0 -49
  716. package/skills/getting-metadata-api-context/data/metadata_api/ConnectedApp.json +0 -384
  717. package/skills/getting-metadata-api-context/data/metadata_api/ConnectedAppSettings.json +0 -40
  718. package/skills/getting-metadata-api-context/data/metadata_api/ContentAsset.json +0 -121
  719. package/skills/getting-metadata-api-context/data/metadata_api/ContentSettings.json +0 -116
  720. package/skills/getting-metadata-api-context/data/metadata_api/ContentTypeBundle.json +0 -64
  721. package/skills/getting-metadata-api-context/data/metadata_api/ContextDefinition.json +0 -340
  722. package/skills/getting-metadata-api-context/data/metadata_api/ContractSettings.json +0 -36
  723. package/skills/getting-metadata-api-context/data/metadata_api/ConvIntelligenceSignalRule.json +0 -106
  724. package/skills/getting-metadata-api-context/data/metadata_api/ConversationChannelDefinition.json +0 -140
  725. package/skills/getting-metadata-api-context/data/metadata_api/ConversationMessageDefinition.json +0 -380
  726. package/skills/getting-metadata-api-context/data/metadata_api/ConversationMessageDefinitionTranslation.json +0 -49
  727. package/skills/getting-metadata-api-context/data/metadata_api/ConversationVendorInfo.json +0 -148
  728. package/skills/getting-metadata-api-context/data/metadata_api/ConversationalIntelligenceSettings.json +0 -76
  729. package/skills/getting-metadata-api-context/data/metadata_api/CorsWhitelistOrigin.json +0 -32
  730. package/skills/getting-metadata-api-context/data/metadata_api/CriteriaBasedSharingRule.json +0 -206
  731. package/skills/getting-metadata-api-context/data/metadata_api/CspTrustedSite.json +0 -82
  732. package/skills/getting-metadata-api-context/data/metadata_api/CurrencySettings.json +0 -48
  733. package/skills/getting-metadata-api-context/data/metadata_api/CustomAddressFieldSettings.json +0 -32
  734. package/skills/getting-metadata-api-context/data/metadata_api/CustomApplication.json +0 -453
  735. package/skills/getting-metadata-api-context/data/metadata_api/CustomApplicationComponent.json +0 -72
  736. package/skills/getting-metadata-api-context/data/metadata_api/CustomFeedFilter.json +0 -63
  737. package/skills/getting-metadata-api-context/data/metadata_api/CustomField.json +0 -392
  738. package/skills/getting-metadata-api-context/data/metadata_api/CustomFieldDisplay.json +0 -45
  739. package/skills/getting-metadata-api-context/data/metadata_api/CustomHelpMenuSection.json +0 -57
  740. package/skills/getting-metadata-api-context/data/metadata_api/CustomIndex.json +0 -36
  741. package/skills/getting-metadata-api-context/data/metadata_api/CustomLabels.json +0 -69
  742. package/skills/getting-metadata-api-context/data/metadata_api/CustomMetadata.json +0 -90
  743. package/skills/getting-metadata-api-context/data/metadata_api/CustomNotificationType.json +0 -94
  744. package/skills/getting-metadata-api-context/data/metadata_api/CustomObject.json +0 -313
  745. package/skills/getting-metadata-api-context/data/metadata_api/CustomObjectTranslation.json +0 -319
  746. package/skills/getting-metadata-api-context/data/metadata_api/CustomPageWebLink.json +0 -121
  747. package/skills/getting-metadata-api-context/data/metadata_api/CustomPermission.json +0 -65
  748. package/skills/getting-metadata-api-context/data/metadata_api/CustomSite.json +0 -288
  749. package/skills/getting-metadata-api-context/data/metadata_api/CustomTab.json +0 -97
  750. package/skills/getting-metadata-api-context/data/metadata_api/CustomValue.json +0 -85
  751. package/skills/getting-metadata-api-context/data/metadata_api/CustomerDataPlatformSettings.json +0 -32
  752. package/skills/getting-metadata-api-context/data/metadata_api/Dashboard.json +0 -584
  753. package/skills/getting-metadata-api-context/data/metadata_api/DataCategoryGroup.json +0 -81
  754. package/skills/getting-metadata-api-context/data/metadata_api/DataConnector.json +0 -230
  755. package/skills/getting-metadata-api-context/data/metadata_api/DataConnectorIngestApi.json +0 -41
  756. package/skills/getting-metadata-api-context/data/metadata_api/DataConnectorS3.json +0 -44
  757. package/skills/getting-metadata-api-context/data/metadata_api/DataDotComSettings.json +0 -56
  758. package/skills/getting-metadata-api-context/data/metadata_api/DataImportManagementSettings.json +0 -32
  759. package/skills/getting-metadata-api-context/data/metadata_api/DataKitObjectDependency.json +0 -49
  760. package/skills/getting-metadata-api-context/data/metadata_api/DataKitObjectTemplate.json +0 -59
  761. package/skills/getting-metadata-api-context/data/metadata_api/DataObjectBuildOrgTemplate.json +0 -61
  762. package/skills/getting-metadata-api-context/data/metadata_api/DataObjectSearchIndexConf.json +0 -62
  763. package/skills/getting-metadata-api-context/data/metadata_api/DataPackageKitDefinition.json +0 -74
  764. package/skills/getting-metadata-api-context/data/metadata_api/DataPackageKitObject.json +0 -47
  765. package/skills/getting-metadata-api-context/data/metadata_api/DataSource.json +0 -29
  766. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceBundleDefinition.json +0 -57
  767. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceField.json +0 -115
  768. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceObject.json +0 -93
  769. package/skills/getting-metadata-api-context/data/metadata_api/DataSourceTenant.json +0 -8
  770. package/skills/getting-metadata-api-context/data/metadata_api/DataSrcDataModelFieldMap.json +0 -69
  771. package/skills/getting-metadata-api-context/data/metadata_api/DataStreamDefinition.json +0 -105
  772. package/skills/getting-metadata-api-context/data/metadata_api/DataStreamTemplate.json +0 -99
  773. package/skills/getting-metadata-api-context/data/metadata_api/DataWeaveResource.json +0 -46
  774. package/skills/getting-metadata-api-context/data/metadata_api/DebuggingHeader.json +0 -20
  775. package/skills/getting-metadata-api-context/data/metadata_api/DecisionMatrixDefinition.json +0 -140
  776. package/skills/getting-metadata-api-context/data/metadata_api/DecisionTable.json +0 -211
  777. package/skills/getting-metadata-api-context/data/metadata_api/DecisionTableDatasetLink.json +0 -72
  778. package/skills/getting-metadata-api-context/data/metadata_api/DelegateGroup.json +0 -62
  779. package/skills/getting-metadata-api-context/data/metadata_api/DeleteResult.json +0 -22
  780. package/skills/getting-metadata-api-context/data/metadata_api/DeployResult.json +0 -253
  781. package/skills/getting-metadata-api-context/data/metadata_api/DeploymentSettings.json +0 -32
  782. package/skills/getting-metadata-api-context/data/metadata_api/DescribeMetadataResult.json +0 -31
  783. package/skills/getting-metadata-api-context/data/metadata_api/DescribeValueTypeResult.json +0 -56
  784. package/skills/getting-metadata-api-context/data/metadata_api/DevHubSettings.json +0 -60
  785. package/skills/getting-metadata-api-context/data/metadata_api/DgtAssetMgmtProvider.json +0 -43
  786. package/skills/getting-metadata-api-context/data/metadata_api/DgtAssetMgmtPrvdLghtCpnt.json +0 -48
  787. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle.json +0 -102
  788. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle_Marketing_Workspace_Bundle_and_Folders.json +0 -8
  789. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceBundle_Site_Workspace_Bundle_and_Folders.json +0 -541
  790. package/skills/getting-metadata-api-context/data/metadata_api/DigitalExperienceConfig.json +0 -51
  791. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureDefinition.json +0 -45
  792. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureDefinitionVersion.json +0 -78
  793. package/skills/getting-metadata-api-context/data/metadata_api/DisclosureType.json +0 -53
  794. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryAIModel.json +0 -263
  795. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryGoal.json +0 -361
  796. package/skills/getting-metadata-api-context/data/metadata_api/DiscoveryStory.json +0 -98
  797. package/skills/getting-metadata-api-context/data/metadata_api/Document.json +0 -54
  798. package/skills/getting-metadata-api-context/data/metadata_api/DocumentCategory.json +0 -42
  799. package/skills/getting-metadata-api-context/data/metadata_api/DocumentCategoryDocumentType.json +0 -48
  800. package/skills/getting-metadata-api-context/data/metadata_api/DocumentChecklistSettings.json +0 -36
  801. package/skills/getting-metadata-api-context/data/metadata_api/DocumentGenerationSetting.json +0 -60
  802. package/skills/getting-metadata-api-context/data/metadata_api/DocumentType.json +0 -43
  803. package/skills/getting-metadata-api-context/data/metadata_api/DuplicateRule.json +0 -160
  804. package/skills/getting-metadata-api-context/data/metadata_api/DynamicFormsSettings.json +0 -32
  805. package/skills/getting-metadata-api-context/data/metadata_api/EACSettings.json +0 -112
  806. package/skills/getting-metadata-api-context/data/metadata_api/EclairGeoData.json +0 -73
  807. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinAISettings.json +0 -45
  808. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinAgentSettings.json +0 -40
  809. package/skills/getting-metadata-api-context/data/metadata_api/EinsteinGptSettings.json +0 -64
  810. package/skills/getting-metadata-api-context/data/metadata_api/EmailAdministrationSettings.json +0 -104
  811. package/skills/getting-metadata-api-context/data/metadata_api/EmailAuthorizationSettings.json +0 -32
  812. package/skills/getting-metadata-api-context/data/metadata_api/EmailIntegrationSettings.json +0 -92
  813. package/skills/getting-metadata-api-context/data/metadata_api/EmailServicesFunction.json +0 -116
  814. package/skills/getting-metadata-api-context/data/metadata_api/EmailTemplate.json +0 -116
  815. package/skills/getting-metadata-api-context/data/metadata_api/EmailTemplateSettings.json +0 -32
  816. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceBranding.json +0 -78
  817. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceConfig.json +0 -318
  818. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceFieldService.json +0 -73
  819. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceFlowConfig.json +0 -32
  820. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceLiveAgent.json +0 -141
  821. package/skills/getting-metadata-api-context/data/metadata_api/EmbeddedServiceMenuSettings.json +0 -165
  822. package/skills/getting-metadata-api-context/data/metadata_api/EmployeeUserSettings.json +0 -54
  823. package/skills/getting-metadata-api-context/data/metadata_api/EnablementMeasureDefinition.json +0 -139
  824. package/skills/getting-metadata-api-context/data/metadata_api/EnablementProgramDefinition.json +0 -241
  825. package/skills/getting-metadata-api-context/data/metadata_api/EnblProgramTaskSubCategory.json +0 -47
  826. package/skills/getting-metadata-api-context/data/metadata_api/EncryptionKeySettings.json +0 -51
  827. package/skills/getting-metadata-api-context/data/metadata_api/EnhancedNotesSettings.json +0 -36
  828. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementProcess.json +0 -147
  829. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementSettings.json +0 -80
  830. package/skills/getting-metadata-api-context/data/metadata_api/EntitlementTemplate.json +0 -52
  831. package/skills/getting-metadata-api-context/data/metadata_api/Error.json +0 -25
  832. package/skills/getting-metadata-api-context/data/metadata_api/EscalationRules.json +0 -117
  833. package/skills/getting-metadata-api-context/data/metadata_api/EventDelivery.json +0 -57
  834. package/skills/getting-metadata-api-context/data/metadata_api/EventRelayConfig.json +0 -55
  835. package/skills/getting-metadata-api-context/data/metadata_api/EventSettings.json +0 -76
  836. package/skills/getting-metadata-api-context/data/metadata_api/EventSubscription.json +0 -62
  837. package/skills/getting-metadata-api-context/data/metadata_api/ExperienceBundle.json +0 -387
  838. package/skills/getting-metadata-api-context/data/metadata_api/ExperienceBundleSettings.json +0 -25
  839. package/skills/getting-metadata-api-context/data/metadata_api/ExperiencePropertyTypeBundle.json +0 -68
  840. package/skills/getting-metadata-api-context/data/metadata_api/ExplainabilityMsgTemplate.json +0 -56
  841. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetDefinition.json +0 -496
  842. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetMessageToken.json +0 -42
  843. package/skills/getting-metadata-api-context/data/metadata_api/ExpressionSetObjectAlias.json +0 -61
  844. package/skills/getting-metadata-api-context/data/metadata_api/ExternalAIModel.json +0 -54
  845. package/skills/getting-metadata-api-context/data/metadata_api/ExternalAuthIdentityProvider.json +0 -79
  846. package/skills/getting-metadata-api-context/data/metadata_api/ExternalClientAppSettings.json +0 -40
  847. package/skills/getting-metadata-api-context/data/metadata_api/ExternalClientApplication.json +0 -72
  848. package/skills/getting-metadata-api-context/data/metadata_api/ExternalCredential.json +0 -94
  849. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataConnector.json +0 -51
  850. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataSource.json +0 -162
  851. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTranObject.json +0 -191
  852. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTransportFieldTemplate.json +0 -8
  853. package/skills/getting-metadata-api-context/data/metadata_api/ExternalDataTransportObjectTemplate.json +0 -8
  854. package/skills/getting-metadata-api-context/data/metadata_api/ExternalServiceRegistration.json +0 -121
  855. package/skills/getting-metadata-api-context/data/metadata_api/ExternalServicesSettings.json +0 -34
  856. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppCanvasSettings.json +0 -63
  857. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppConfigurablePolicies.json +0 -75
  858. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppGlobalOauthSettings.json +0 -135
  859. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppMobileConfigurablePolicies.json +0 -34
  860. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppMobileSettings.json +0 -35
  861. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppNotificationSettings.json +0 -49
  862. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppOauthConfigurablePolicies.json +0 -153
  863. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppOauthSettings.json +0 -120
  864. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppPushConfigurablePolicies.json +0 -35
  865. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppPushSettings.json +0 -93
  866. package/skills/getting-metadata-api-context/data/metadata_api/ExtlClntAppSamlConfigurablePolicies.json +0 -119
  867. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterBoolean.json +0 -47
  868. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterDate.json +0 -47
  869. package/skills/getting-metadata-api-context/data/metadata_api/FeatureParameterInteger.json +0 -47
  870. package/skills/getting-metadata-api-context/data/metadata_api/FieldMappingConfig.json +0 -43
  871. package/skills/getting-metadata-api-context/data/metadata_api/FieldRestrictionRule.json +0 -80
  872. package/skills/getting-metadata-api-context/data/metadata_api/FieldServiceSettings.json +0 -226
  873. package/skills/getting-metadata-api-context/data/metadata_api/FieldSet.json +0 -60
  874. package/skills/getting-metadata-api-context/data/metadata_api/FieldSrcTrgtRelationship.json +0 -56
  875. package/skills/getting-metadata-api-context/data/metadata_api/FileUploadAndDownloadSecuritySettings.json +0 -53
  876. package/skills/getting-metadata-api-context/data/metadata_api/FilesConnectSettings.json +0 -40
  877. package/skills/getting-metadata-api-context/data/metadata_api/FlexiPage.json +0 -355
  878. package/skills/getting-metadata-api-context/data/metadata_api/Flow.json +0 -2377
  879. package/skills/getting-metadata-api-context/data/metadata_api/FlowCategory.json +0 -51
  880. package/skills/getting-metadata-api-context/data/metadata_api/FlowDefinition.json +0 -37
  881. package/skills/getting-metadata-api-context/data/metadata_api/FlowSettings.json +0 -124
  882. package/skills/getting-metadata-api-context/data/metadata_api/FlowTest.json +0 -205
  883. package/skills/getting-metadata-api-context/data/metadata_api/FlowValueMap.json +0 -68
  884. package/skills/getting-metadata-api-context/data/metadata_api/Folder.json +0 -50
  885. package/skills/getting-metadata-api-context/data/metadata_api/FolderShare.json +0 -45
  886. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingFilter.json +0 -48
  887. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingFilterCondition.json +0 -62
  888. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingObjectListSettings.json +0 -77
  889. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingSettings.json +0 -303
  890. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingSourceDefinition.json +0 -62
  891. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingType.json +0 -100
  892. package/skills/getting-metadata-api-context/data/metadata_api/ForecastingTypeSource.json +0 -60
  893. package/skills/getting-metadata-api-context/data/metadata_api/FuelType.json +0 -52
  894. package/skills/getting-metadata-api-context/data/metadata_api/FuelTypeSustnUom.json +0 -45
  895. package/skills/getting-metadata-api-context/data/metadata_api/FunctionReference.json +0 -31
  896. package/skills/getting-metadata-api-context/data/metadata_api/FundraisingConfig.json +0 -86
  897. package/skills/getting-metadata-api-context/data/metadata_api/GatewayProviderPaymentMethodType.json +0 -50
  898. package/skills/getting-metadata-api-context/data/metadata_api/GenAiFunction.json +0 -171
  899. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlanner.json +0 -215
  900. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlannerBundle.json +0 -220
  901. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPlugin.json +0 -87
  902. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPluginInstructionDef.json +0 -42
  903. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPromptTemplate.json +0 -183
  904. package/skills/getting-metadata-api-context/data/metadata_api/GenAiPromptTemplateActv.json +0 -42
  905. package/skills/getting-metadata-api-context/data/metadata_api/GiftEntryGridTemplate.json +0 -42
  906. package/skills/getting-metadata-api-context/data/metadata_api/GlobalPicklist.json +0 -43
  907. package/skills/getting-metadata-api-context/data/metadata_api/GlobalPicklistValue.json +0 -81
  908. package/skills/getting-metadata-api-context/data/metadata_api/GlobalValueSet.json +0 -46
  909. package/skills/getting-metadata-api-context/data/metadata_api/GlobalValueSetTranslation.json +0 -44
  910. package/skills/getting-metadata-api-context/data/metadata_api/GoogleAppsSettings.json +0 -56
  911. package/skills/getting-metadata-api-context/data/metadata_api/Group.json +0 -46
  912. package/skills/getting-metadata-api-context/data/metadata_api/HighVelocitySalesSettings.json +0 -96
  913. package/skills/getting-metadata-api-context/data/metadata_api/HistoryRetentionPolicy.json +0 -41
  914. package/skills/getting-metadata-api-context/data/metadata_api/HomePageComponent.json +0 -66
  915. package/skills/getting-metadata-api-context/data/metadata_api/HomePageLayout.json +0 -40
  916. package/skills/getting-metadata-api-context/data/metadata_api/IPAddressRange.json +0 -60
  917. package/skills/getting-metadata-api-context/data/metadata_api/IdeasSettings.json +0 -52
  918. package/skills/getting-metadata-api-context/data/metadata_api/IdentityProviderSettings.json +0 -39
  919. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcDef.json +0 -173
  920. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcDtl.json +0 -136
  921. package/skills/getting-metadata-api-context/data/metadata_api/IdentityVerificationProcFld.json +0 -76
  922. package/skills/getting-metadata-api-context/data/metadata_api/IframeWhiteListUrlSettings.json +0 -46
  923. package/skills/getting-metadata-api-context/data/metadata_api/InboundCertificate.json +0 -48
  924. package/skills/getting-metadata-api-context/data/metadata_api/InboundNetworkConnection.json +0 -72
  925. package/skills/getting-metadata-api-context/data/metadata_api/IncidentMgmtSettings.json +0 -140
  926. package/skills/getting-metadata-api-context/data/metadata_api/Index.json +0 -48
  927. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesEinsteinFeatureSettings.json +0 -34
  928. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesLoyaltySettings.json +0 -108
  929. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesPricingSettings.json +0 -61
  930. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesRatingSettings.json +0 -40
  931. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesSettings.json +0 -731
  932. package/skills/getting-metadata-api-context/data/metadata_api/IndustriesUnifiedInventorySettings.json +0 -40
  933. package/skills/getting-metadata-api-context/data/metadata_api/InsPlcyLimitConsumptionRule.json +0 -46
  934. package/skills/getting-metadata-api-context/data/metadata_api/InstalledPackage.json +0 -46
  935. package/skills/getting-metadata-api-context/data/metadata_api/IntegArtifactDef.json +0 -10
  936. package/skills/getting-metadata-api-context/data/metadata_api/IntegrationProviderDef.json +0 -155
  937. package/skills/getting-metadata-api-context/data/metadata_api/InterestTaggingSettings.json +0 -32
  938. package/skills/getting-metadata-api-context/data/metadata_api/InternalDataConnector.json +0 -8
  939. package/skills/getting-metadata-api-context/data/metadata_api/InvLatePymntRiskCalcSettings.json +0 -32
  940. package/skills/getting-metadata-api-context/data/metadata_api/InventorySettings.json +0 -36
  941. package/skills/getting-metadata-api-context/data/metadata_api/InvocableActionExtension.json +0 -84
  942. package/skills/getting-metadata-api-context/data/metadata_api/InvocableActionSettings.json +0 -28
  943. package/skills/getting-metadata-api-context/data/metadata_api/KeywordList.json +0 -51
  944. package/skills/getting-metadata-api-context/data/metadata_api/KnowledgeSettings.json +0 -280
  945. package/skills/getting-metadata-api-context/data/metadata_api/LanguageSettings.json +0 -68
  946. package/skills/getting-metadata-api-context/data/metadata_api/Layout.json +0 -659
  947. package/skills/getting-metadata-api-context/data/metadata_api/LeadConfigSettings.json +0 -64
  948. package/skills/getting-metadata-api-context/data/metadata_api/LeadConvertSettings.json +0 -71
  949. package/skills/getting-metadata-api-context/data/metadata_api/LearningItemType.json +0 -65
  950. package/skills/getting-metadata-api-context/data/metadata_api/Letterhead.json +0 -119
  951. package/skills/getting-metadata-api-context/data/metadata_api/LightningBolt.json +0 -103
  952. package/skills/getting-metadata-api-context/data/metadata_api/LightningComponentBundle.json +0 -109
  953. package/skills/getting-metadata-api-context/data/metadata_api/LightningExperienceSettings.json +0 -191
  954. package/skills/getting-metadata-api-context/data/metadata_api/LightningExperienceTheme.json +0 -54
  955. package/skills/getting-metadata-api-context/data/metadata_api/LightningMessageChannel.json +0 -63
  956. package/skills/getting-metadata-api-context/data/metadata_api/LightningOnboardingConfig.json +0 -62
  957. package/skills/getting-metadata-api-context/data/metadata_api/LightningTypeBundle.json +0 -88
  958. package/skills/getting-metadata-api-context/data/metadata_api/ListMetadataQuery.json +0 -10
  959. package/skills/getting-metadata-api-context/data/metadata_api/ListView.json +0 -86
  960. package/skills/getting-metadata-api-context/data/metadata_api/LiveAgentSettings.json +0 -44
  961. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatAgentConfig.json +0 -188
  962. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatButton.json +0 -188
  963. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatDeployment.json +0 -81
  964. package/skills/getting-metadata-api-context/data/metadata_api/LiveChatSensitiveDataRule.json +0 -56
  965. package/skills/getting-metadata-api-context/data/metadata_api/LiveMessageSettings.json +0 -36
  966. package/skills/getting-metadata-api-context/data/metadata_api/LoyaltyProgramSetup.json +0 -297
  967. package/skills/getting-metadata-api-context/data/metadata_api/MLDataDefinition.json +0 -146
  968. package/skills/getting-metadata-api-context/data/metadata_api/MLPredictionDefinition.json +0 -67
  969. package/skills/getting-metadata-api-context/data/metadata_api/MacroSettings.json +0 -36
  970. package/skills/getting-metadata-api-context/data/metadata_api/MailMergeSettings.json +0 -36
  971. package/skills/getting-metadata-api-context/data/metadata_api/ManagedContentType.json +0 -86
  972. package/skills/getting-metadata-api-context/data/metadata_api/ManagedEventSubscription.json +0 -52
  973. package/skills/getting-metadata-api-context/data/metadata_api/ManagedTopics.json +0 -57
  974. package/skills/getting-metadata-api-context/data/metadata_api/MapAndLocationSettings.json +0 -34
  975. package/skills/getting-metadata-api-context/data/metadata_api/MarketSegmentDefinition.json +0 -58
  976. package/skills/getting-metadata-api-context/data/metadata_api/MarketingAppExtension.json +0 -139
  977. package/skills/getting-metadata-api-context/data/metadata_api/MatchingRule.json +0 -69
  978. package/skills/getting-metadata-api-context/data/metadata_api/MeetingsSettings.json +0 -36
  979. package/skills/getting-metadata-api-context/data/metadata_api/MessagingChannel.json +0 -278
  980. package/skills/getting-metadata-api-context/data/metadata_api/MetadataWithContent.json +0 -24
  981. package/skills/getting-metadata-api-context/data/metadata_api/Metadata_Type_Limits.json +0 -8
  982. package/skills/getting-metadata-api-context/data/metadata_api/MfgProgramTemplate.json +0 -88
  983. package/skills/getting-metadata-api-context/data/metadata_api/MfgServiceConsoleSettings.json +0 -32
  984. package/skills/getting-metadata-api-context/data/metadata_api/MilestoneType.json +0 -36
  985. package/skills/getting-metadata-api-context/data/metadata_api/MktCalcInsightObjectDef.json +0 -54
  986. package/skills/getting-metadata-api-context/data/metadata_api/MktDataTranObject.json +0 -99
  987. package/skills/getting-metadata-api-context/data/metadata_api/MlDomain.json +0 -136
  988. package/skills/getting-metadata-api-context/data/metadata_api/MobSecurityCertPinConfig.json +0 -76
  989. package/skills/getting-metadata-api-context/data/metadata_api/MobileApplicationDetail.json +0 -71
  990. package/skills/getting-metadata-api-context/data/metadata_api/MobileSecurityAssignment.json +0 -44
  991. package/skills/getting-metadata-api-context/data/metadata_api/MobileSecurityPolicy.json +0 -75
  992. package/skills/getting-metadata-api-context/data/metadata_api/MobileSettings.json +0 -121
  993. package/skills/getting-metadata-api-context/data/metadata_api/ModerationRule.json +0 -99
  994. package/skills/getting-metadata-api-context/data/metadata_api/MutingPermissionSet.json +0 -33
  995. package/skills/getting-metadata-api-context/data/metadata_api/MyDomainDiscoverableLogin.json +0 -41
  996. package/skills/getting-metadata-api-context/data/metadata_api/MyDomainSettings.json +0 -140
  997. package/skills/getting-metadata-api-context/data/metadata_api/NameSettings.json +0 -40
  998. package/skills/getting-metadata-api-context/data/metadata_api/NamedCredential.json +0 -205
  999. package/skills/getting-metadata-api-context/data/metadata_api/NamedFilter.json +0 -89
  1000. package/skills/getting-metadata-api-context/data/metadata_api/NavigationMenu.json +0 -101
  1001. package/skills/getting-metadata-api-context/data/metadata_api/Network.json +0 -606
  1002. package/skills/getting-metadata-api-context/data/metadata_api/NetworkBranding.json +0 -117
  1003. package/skills/getting-metadata-api-context/data/metadata_api/NotificationTypeConfig.json +0 -75
  1004. package/skills/getting-metadata-api-context/data/metadata_api/NotificationsSettings.json +0 -40
  1005. package/skills/getting-metadata-api-context/data/metadata_api/OauthCustomScope.json +0 -56
  1006. package/skills/getting-metadata-api-context/data/metadata_api/OauthOidcSettings.json +0 -52
  1007. package/skills/getting-metadata-api-context/data/metadata_api/OauthTokenExchangeHandler.json +0 -119
  1008. package/skills/getting-metadata-api-context/data/metadata_api/ObjectHierarchyRelationship.json +0 -108
  1009. package/skills/getting-metadata-api-context/data/metadata_api/ObjectLinkingSettings.json +0 -32
  1010. package/skills/getting-metadata-api-context/data/metadata_api/ObjectSourceTargetMap.json +0 -85
  1011. package/skills/getting-metadata-api-context/data/metadata_api/OcrSampleDocument.json +0 -158
  1012. package/skills/getting-metadata-api-context/data/metadata_api/OcrTemplate.json +0 -180
  1013. package/skills/getting-metadata-api-context/data/metadata_api/OmniChannelSettings.json +0 -48
  1014. package/skills/getting-metadata-api-context/data/metadata_api/OmniExtTrackingDef.json +0 -66
  1015. package/skills/getting-metadata-api-context/data/metadata_api/OmniInteractionAccessConfig.json +0 -90
  1016. package/skills/getting-metadata-api-context/data/metadata_api/OmniInteractionConfig.json +0 -37
  1017. package/skills/getting-metadata-api-context/data/metadata_api/OmniScript.json +0 -204
  1018. package/skills/getting-metadata-api-context/data/metadata_api/OmniSupervisorConfig.json +0 -156
  1019. package/skills/getting-metadata-api-context/data/metadata_api/OmniTrackingGroup.json +0 -77
  1020. package/skills/getting-metadata-api-context/data/metadata_api/OnboardingDataObjectGroup.json +0 -131
  1021. package/skills/getting-metadata-api-context/data/metadata_api/OpportunityInsightsSettings.json +0 -30
  1022. package/skills/getting-metadata-api-context/data/metadata_api/OpportunityScoreSettings.json +0 -32
  1023. package/skills/getting-metadata-api-context/data/metadata_api/OpportunitySettings.json +0 -132
  1024. package/skills/getting-metadata-api-context/data/metadata_api/OrchestrationPlanCtxMapping.json +0 -63
  1025. package/skills/getting-metadata-api-context/data/metadata_api/OrderManagementSettings.json +0 -52
  1026. package/skills/getting-metadata-api-context/data/metadata_api/OrderSettings.json +0 -60
  1027. package/skills/getting-metadata-api-context/data/metadata_api/OrgPreferenceSettings.json +0 -43
  1028. package/skills/getting-metadata-api-context/data/metadata_api/OrgSettings.json +0 -40
  1029. package/skills/getting-metadata-api-context/data/metadata_api/OutboundNetworkConnection.json +0 -71
  1030. package/skills/getting-metadata-api-context/data/metadata_api/OwnerSharingRule.json +0 -206
  1031. package/skills/getting-metadata-api-context/data/metadata_api/Package.json +0 -19
  1032. package/skills/getting-metadata-api-context/data/metadata_api/PardotEinsteinSettings.json +0 -36
  1033. package/skills/getting-metadata-api-context/data/metadata_api/PardotSettings.json +0 -72
  1034. package/skills/getting-metadata-api-context/data/metadata_api/ParticipantRole.json +0 -48
  1035. package/skills/getting-metadata-api-context/data/metadata_api/PartyDataModelSettings.json +0 -40
  1036. package/skills/getting-metadata-api-context/data/metadata_api/PathAssistant.json +0 -74
  1037. package/skills/getting-metadata-api-context/data/metadata_api/PathAssistantSettings.json +0 -40
  1038. package/skills/getting-metadata-api-context/data/metadata_api/PaymentGatewayProvider.json +0 -50
  1039. package/skills/getting-metadata-api-context/data/metadata_api/PaymentsSettings.json +0 -32
  1040. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSet.json +0 -372
  1041. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSetGroup.json +0 -57
  1042. package/skills/getting-metadata-api-context/data/metadata_api/PermissionSetLicenseDefinition.json +0 -58
  1043. package/skills/getting-metadata-api-context/data/metadata_api/PersonAccountOwnerPowerUser.json +0 -38
  1044. package/skills/getting-metadata-api-context/data/metadata_api/Picklist.json +0 -43
  1045. package/skills/getting-metadata-api-context/data/metadata_api/PicklistSettings.json +0 -32
  1046. package/skills/getting-metadata-api-context/data/metadata_api/PipelineInspMetricConfig.json +0 -48
  1047. package/skills/getting-metadata-api-context/data/metadata_api/PlatformCachePartition.json +0 -79
  1048. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEncryptionSettings.json +0 -51
  1049. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventChannel.json +0 -56
  1050. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventChannelMember.json +0 -71
  1051. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventMigration.json +0 -39
  1052. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventSettings.json +0 -32
  1053. package/skills/getting-metadata-api-context/data/metadata_api/PlatformEventSubscriberConfig.json +0 -58
  1054. package/skills/getting-metadata-api-context/data/metadata_api/Portal.json +0 -137
  1055. package/skills/getting-metadata-api-context/data/metadata_api/PortalDelegablePermissionSet.json +0 -48
  1056. package/skills/getting-metadata-api-context/data/metadata_api/PostTemplate.json +0 -47
  1057. package/skills/getting-metadata-api-context/data/metadata_api/PredictionBuilderSettings.json +0 -36
  1058. package/skills/getting-metadata-api-context/data/metadata_api/PresenceDeclineReason.json +0 -32
  1059. package/skills/getting-metadata-api-context/data/metadata_api/PresenceUserConfig.json +0 -122
  1060. package/skills/getting-metadata-api-context/data/metadata_api/PricingActionParameters.json +0 -64
  1061. package/skills/getting-metadata-api-context/data/metadata_api/PricingRecipe.json +0 -117
  1062. package/skills/getting-metadata-api-context/data/metadata_api/PrivacySettings.json +0 -80
  1063. package/skills/getting-metadata-api-context/data/metadata_api/ProcessFlowMigration.json +0 -58
  1064. package/skills/getting-metadata-api-context/data/metadata_api/ProductAttributeSet.json +0 -33
  1065. package/skills/getting-metadata-api-context/data/metadata_api/ProductSettings.json +0 -44
  1066. package/skills/getting-metadata-api-context/data/metadata_api/Profile.json +0 -492
  1067. package/skills/getting-metadata-api-context/data/metadata_api/ProfileActionOverride.json +0 -48
  1068. package/skills/getting-metadata-api-context/data/metadata_api/ProfilePasswordPolicy.json +0 -80
  1069. package/skills/getting-metadata-api-context/data/metadata_api/ProfileSearchLayouts.json +0 -32
  1070. package/skills/getting-metadata-api-context/data/metadata_api/ProfileSessionSetting.json +0 -55
  1071. package/skills/getting-metadata-api-context/data/metadata_api/Prompt.json +0 -255
  1072. package/skills/getting-metadata-api-context/data/metadata_api/PublicKeyCertificate.json +0 -50
  1073. package/skills/getting-metadata-api-context/data/metadata_api/PublicKeyCertificateSet.json +0 -65
  1074. package/skills/getting-metadata-api-context/data/metadata_api/Queue.json +0 -123
  1075. package/skills/getting-metadata-api-context/data/metadata_api/QueueRoutingConfig.json +0 -96
  1076. package/skills/getting-metadata-api-context/data/metadata_api/QuickAction.json +0 -175
  1077. package/skills/getting-metadata-api-context/data/metadata_api/QuoteSettings.json +0 -36
  1078. package/skills/getting-metadata-api-context/data/metadata_api/ReadResult.json +0 -16
  1079. package/skills/getting-metadata-api-context/data/metadata_api/RealTimeEventSettings.json +0 -45
  1080. package/skills/getting-metadata-api-context/data/metadata_api/RecommendationStrategy.json +0 -327
  1081. package/skills/getting-metadata-api-context/data/metadata_api/RecordActionDeployment.json +0 -184
  1082. package/skills/getting-metadata-api-context/data/metadata_api/RecordAggregationDefinition.json +0 -148
  1083. package/skills/getting-metadata-api-context/data/metadata_api/RecordAlertCategory.json +0 -42
  1084. package/skills/getting-metadata-api-context/data/metadata_api/RecordPageSettings.json +0 -40
  1085. package/skills/getting-metadata-api-context/data/metadata_api/RecordType.json +0 -68
  1086. package/skills/getting-metadata-api-context/data/metadata_api/RedirectWhitelistUrl.json +0 -26
  1087. package/skills/getting-metadata-api-context/data/metadata_api/ReferencedDashboard.json +0 -55
  1088. package/skills/getting-metadata-api-context/data/metadata_api/RegisteredExternalService.json +0 -72
  1089. package/skills/getting-metadata-api-context/data/metadata_api/RelatedRecordAssocCriteria.json +0 -75
  1090. package/skills/getting-metadata-api-context/data/metadata_api/RelationshipGraphDefinition.json +0 -63
  1091. package/skills/getting-metadata-api-context/data/metadata_api/RemoteSiteSetting.json +0 -51
  1092. package/skills/getting-metadata-api-context/data/metadata_api/Report.json +0 -715
  1093. package/skills/getting-metadata-api-context/data/metadata_api/ReportType.json +0 -118
  1094. package/skills/getting-metadata-api-context/data/metadata_api/RestrictionRule.json +0 -71
  1095. package/skills/getting-metadata-api-context/data/metadata_api/RetailExecutionSettings.json +0 -40
  1096. package/skills/getting-metadata-api-context/data/metadata_api/RetrievalSummaryDefinition.json +0 -76
  1097. package/skills/getting-metadata-api-context/data/metadata_api/RetrieveRequest.json +0 -35
  1098. package/skills/getting-metadata-api-context/data/metadata_api/RetrieveResult.json +0 -103
  1099. package/skills/getting-metadata-api-context/data/metadata_api/Role.json +0 -35
  1100. package/skills/getting-metadata-api-context/data/metadata_api/RoleOrTerritory.json +0 -57
  1101. package/skills/getting-metadata-api-context/data/metadata_api/SalesAgreementSettings.json +0 -180
  1102. package/skills/getting-metadata-api-context/data/metadata_api/SalesWorkQueueSettings.json +0 -40
  1103. package/skills/getting-metadata-api-context/data/metadata_api/SamlSsoConfig.json +0 -128
  1104. package/skills/getting-metadata-api-context/data/metadata_api/SandboxSettings.json +0 -32
  1105. package/skills/getting-metadata-api-context/data/metadata_api/SaveResult.json +0 -22
  1106. package/skills/getting-metadata-api-context/data/metadata_api/SchedulingObjective.json +0 -66
  1107. package/skills/getting-metadata-api-context/data/metadata_api/SchedulingRule.json +0 -66
  1108. package/skills/getting-metadata-api-context/data/metadata_api/SchemaSettings.json +0 -44
  1109. package/skills/getting-metadata-api-context/data/metadata_api/Scontrol.json +0 -72
  1110. package/skills/getting-metadata-api-context/data/metadata_api/SearchCustomization.json +0 -120
  1111. package/skills/getting-metadata-api-context/data/metadata_api/SearchLayouts.json +0 -64
  1112. package/skills/getting-metadata-api-context/data/metadata_api/SearchOrgWideObjectConfig.json +0 -61
  1113. package/skills/getting-metadata-api-context/data/metadata_api/SearchSettings.json +0 -155
  1114. package/skills/getting-metadata-api-context/data/metadata_api/SecuritySettings.json +0 -437
  1115. package/skills/getting-metadata-api-context/data/metadata_api/ServiceAISetupDefinition.json +0 -48
  1116. package/skills/getting-metadata-api-context/data/metadata_api/ServiceAISetupField.json +0 -58
  1117. package/skills/getting-metadata-api-context/data/metadata_api/ServiceChannel.json +0 -123
  1118. package/skills/getting-metadata-api-context/data/metadata_api/ServiceCloudVoiceSettings.json +0 -83
  1119. package/skills/getting-metadata-api-context/data/metadata_api/ServicePresenceStatus.json +0 -45
  1120. package/skills/getting-metadata-api-context/data/metadata_api/ServiceProcess.json +0 -141
  1121. package/skills/getting-metadata-api-context/data/metadata_api/ServiceSetupAssistantSettings.json +0 -32
  1122. package/skills/getting-metadata-api-context/data/metadata_api/SessionHeader.json +0 -17
  1123. package/skills/getting-metadata-api-context/data/metadata_api/SharedTo.json +0 -105
  1124. package/skills/getting-metadata-api-context/data/metadata_api/SharingBaseRule.json +0 -60
  1125. package/skills/getting-metadata-api-context/data/metadata_api/SharingReason.json +0 -34
  1126. package/skills/getting-metadata-api-context/data/metadata_api/SharingRecalculation.json +0 -29
  1127. package/skills/getting-metadata-api-context/data/metadata_api/SharingRules.json +0 -186
  1128. package/skills/getting-metadata-api-context/data/metadata_api/SharingSet.json +0 -78
  1129. package/skills/getting-metadata-api-context/data/metadata_api/SharingSettings.json +0 -92
  1130. package/skills/getting-metadata-api-context/data/metadata_api/SiteDotCom.json +0 -37
  1131. package/skills/getting-metadata-api-context/data/metadata_api/SiteSettings.json +0 -60
  1132. package/skills/getting-metadata-api-context/data/metadata_api/Skill.json +0 -69
  1133. package/skills/getting-metadata-api-context/data/metadata_api/SocialCustomerServiceSettings.json +0 -61
  1134. package/skills/getting-metadata-api-context/data/metadata_api/SocialProfileSettings.json +0 -35
  1135. package/skills/getting-metadata-api-context/data/metadata_api/SourceTrackingSettings.json +0 -32
  1136. package/skills/getting-metadata-api-context/data/metadata_api/StageAssignment.json +0 -113
  1137. package/skills/getting-metadata-api-context/data/metadata_api/StageDefinition.json +0 -237
  1138. package/skills/getting-metadata-api-context/data/metadata_api/StandardValueSet.json +0 -41
  1139. package/skills/getting-metadata-api-context/data/metadata_api/StandardValueSetTranslation.json +0 -32
  1140. package/skills/getting-metadata-api-context/data/metadata_api/StaticResource.json +0 -49
  1141. package/skills/getting-metadata-api-context/data/metadata_api/StreamingAppDataConnector.json +0 -51
  1142. package/skills/getting-metadata-api-context/data/metadata_api/SubscriptionManagementSettings.json +0 -56
  1143. package/skills/getting-metadata-api-context/data/metadata_api/SurveySettings.json +0 -44
  1144. package/skills/getting-metadata-api-context/data/metadata_api/SustainabilityUom.json +0 -61
  1145. package/skills/getting-metadata-api-context/data/metadata_api/SustnUomConversion.json +0 -58
  1146. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogCategory.json +0 -54
  1147. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogFulfillmentFlow.json +0 -99
  1148. package/skills/getting-metadata-api-context/data/metadata_api/SvcCatalogItemDef.json +0 -202
  1149. package/skills/getting-metadata-api-context/data/metadata_api/SynonymDictionary.json +0 -56
  1150. package/skills/getting-metadata-api-context/data/metadata_api/Tag.json +0 -70
  1151. package/skills/getting-metadata-api-context/data/metadata_api/TagSet.json +0 -47
  1152. package/skills/getting-metadata-api-context/data/metadata_api/Territory.json +0 -39
  1153. package/skills/getting-metadata-api-context/data/metadata_api/Territory2.json +0 -112
  1154. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Model.json +0 -41
  1155. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Rule.json +0 -68
  1156. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Settings.json +0 -111
  1157. package/skills/getting-metadata-api-context/data/metadata_api/Territory2Type.json +0 -42
  1158. package/skills/getting-metadata-api-context/data/metadata_api/TimeSheetTemplate.json +0 -75
  1159. package/skills/getting-metadata-api-context/data/metadata_api/TimelineObjectDefinition.json +0 -48
  1160. package/skills/getting-metadata-api-context/data/metadata_api/TopicsForObjects.json +0 -38
  1161. package/skills/getting-metadata-api-context/data/metadata_api/TrailheadSettings.json +0 -40
  1162. package/skills/getting-metadata-api-context/data/metadata_api/TransactionSecurityPolicy.json +0 -127
  1163. package/skills/getting-metadata-api-context/data/metadata_api/Translations.json +0 -976
  1164. package/skills/getting-metadata-api-context/data/metadata_api/TrialOrgSettings.json +0 -32
  1165. package/skills/getting-metadata-api-context/data/metadata_api/UIBundle.json +0 -54
  1166. package/skills/getting-metadata-api-context/data/metadata_api/UIObjectRelationConfig.json +0 -101
  1167. package/skills/getting-metadata-api-context/data/metadata_api/UiFormatSpecificationSet.json +0 -103
  1168. package/skills/getting-metadata-api-context/data/metadata_api/UiPreviewMessageTabDef.json +0 -70
  1169. package/skills/getting-metadata-api-context/data/metadata_api/UpsertResult.json +0 -25
  1170. package/skills/getting-metadata-api-context/data/metadata_api/UserAccessPolicy.json +0 -120
  1171. package/skills/getting-metadata-api-context/data/metadata_api/UserAuthCertificate.json +0 -57
  1172. package/skills/getting-metadata-api-context/data/metadata_api/UserCriteria.json +0 -48
  1173. package/skills/getting-metadata-api-context/data/metadata_api/UserEngagementSettings.json +0 -136
  1174. package/skills/getting-metadata-api-context/data/metadata_api/UserInterfaceSettings.json +0 -96
  1175. package/skills/getting-metadata-api-context/data/metadata_api/UserManagementSettings.json +0 -108
  1176. package/skills/getting-metadata-api-context/data/metadata_api/UserProfileSearchScope.json +0 -8
  1177. package/skills/getting-metadata-api-context/data/metadata_api/UserProvisioningConfig.json +0 -72
  1178. package/skills/getting-metadata-api-context/data/metadata_api/ValidationRule.json +0 -51
  1179. package/skills/getting-metadata-api-context/data/metadata_api/VirtualVisitConfig.json +0 -97
  1180. package/skills/getting-metadata-api-context/data/metadata_api/VoiceSettings.json +0 -68
  1181. package/skills/getting-metadata-api-context/data/metadata_api/WarrantyLifeCycleMgmtSettings.json +0 -32
  1182. package/skills/getting-metadata-api-context/data/metadata_api/WaveAnalyticAssetCollection.json +0 -73
  1183. package/skills/getting-metadata-api-context/data/metadata_api/WaveApplication.json +0 -56
  1184. package/skills/getting-metadata-api-context/data/metadata_api/WaveComponent.json +0 -46
  1185. package/skills/getting-metadata-api-context/data/metadata_api/WaveDashboard.json +0 -50
  1186. package/skills/getting-metadata-api-context/data/metadata_api/WaveDataflow.json +0 -45
  1187. package/skills/getting-metadata-api-context/data/metadata_api/WaveDataset.json +0 -50
  1188. package/skills/getting-metadata-api-context/data/metadata_api/WaveLens.json +0 -59
  1189. package/skills/getting-metadata-api-context/data/metadata_api/WaveRecipe.json +0 -58
  1190. package/skills/getting-metadata-api-context/data/metadata_api/WaveTemplateBundle.json +0 -37
  1191. package/skills/getting-metadata-api-context/data/metadata_api/WaveXmd.json +0 -567
  1192. package/skills/getting-metadata-api-context/data/metadata_api/WebLink.json +0 -117
  1193. package/skills/getting-metadata-api-context/data/metadata_api/WebStoreBundle.json +0 -10
  1194. package/skills/getting-metadata-api-context/data/metadata_api/WebStoreTemplate.json +0 -166
  1195. package/skills/getting-metadata-api-context/data/metadata_api/WorkDotComSettings.json +0 -76
  1196. package/skills/getting-metadata-api-context/data/metadata_api/WorkSkillRouting.json +0 -76
  1197. package/skills/getting-metadata-api-context/data/metadata_api/Workflow.json +0 -415
  1198. package/skills/getting-metadata-api-context/data/metadata_api/WorkforceEngagementSettings.json +0 -56
  1199. package/skills/getting-metadata-api-context/examples/README.md +0 -169
  1200. package/skills/getting-metadata-api-context/examples/bash_section_loading.sh +0 -142
  1201. package/skills/getting-metadata-api-context/examples/javascript_section_loading.js +0 -162
  1202. package/skills/getting-metadata-api-context/examples/python_section_loading.py +0 -112
  1203. package/skills/getting-metadata-api-context/references/metadata_index_table.md +0 -654
  1204. package/skills/getting-metadata-api-context/references/usage_guide.md +0 -420
  1205. package/skills/handling-sf-data/CREDITS.md +0 -5
  1206. package/skills/handling-sf-data/README.md +0 -112
  1207. package/skills/handling-sf-data/SKILL.md +0 -234
  1208. package/skills/handling-sf-data/assets/bulk/bulk-insert-10000.apex +0 -293
  1209. package/skills/handling-sf-data/assets/bulk/bulk-insert-200.apex +0 -208
  1210. package/skills/handling-sf-data/assets/bulk/bulk-insert-500.apex +0 -219
  1211. package/skills/handling-sf-data/assets/bulk/bulk-upsert-external-id.apex +0 -324
  1212. package/skills/handling-sf-data/assets/cleanup/delete-by-created-date.apex +0 -319
  1213. package/skills/handling-sf-data/assets/cleanup/delete-by-name.apex +0 -240
  1214. package/skills/handling-sf-data/assets/cleanup/delete-test-data.apex +0 -311
  1215. package/skills/handling-sf-data/assets/cleanup/rollback-transaction.apex +0 -266
  1216. package/skills/handling-sf-data/assets/csv/account-import.csv +0 -11
  1217. package/skills/handling-sf-data/assets/csv/contact-import.csv +0 -11
  1218. package/skills/handling-sf-data/assets/csv/custom-object-import.csv +0 -11
  1219. package/skills/handling-sf-data/assets/csv/opportunity-import.csv +0 -11
  1220. package/skills/handling-sf-data/assets/factories/account-factory.apex +0 -165
  1221. package/skills/handling-sf-data/assets/factories/case-factory.apex +0 -237
  1222. package/skills/handling-sf-data/assets/factories/contact-factory.apex +0 -168
  1223. package/skills/handling-sf-data/assets/factories/custom-object-factory.apex +0 -260
  1224. package/skills/handling-sf-data/assets/factories/event-factory.apex +0 -275
  1225. package/skills/handling-sf-data/assets/factories/hierarchy-factory.apex +0 -372
  1226. package/skills/handling-sf-data/assets/factories/lead-factory.apex +0 -190
  1227. package/skills/handling-sf-data/assets/factories/opportunity-factory.apex +0 -206
  1228. package/skills/handling-sf-data/assets/factories/task-factory.apex +0 -246
  1229. package/skills/handling-sf-data/assets/factories/user-factory.apex +0 -278
  1230. package/skills/handling-sf-data/assets/json/account-contact-tree.json +0 -130
  1231. package/skills/handling-sf-data/assets/json/account-opportunity-tree.json +0 -110
  1232. package/skills/handling-sf-data/assets/json/full-hierarchy-tree.json +0 -188
  1233. package/skills/handling-sf-data/assets/soql/aggregate.soql +0 -226
  1234. package/skills/handling-sf-data/assets/soql/child-to-parent.soql +0 -162
  1235. package/skills/handling-sf-data/assets/soql/parent-to-child.soql +0 -153
  1236. package/skills/handling-sf-data/assets/soql/polymorphic.soql +0 -198
  1237. package/skills/handling-sf-data/assets/soql/subquery.soql +0 -287
  1238. package/skills/handling-sf-data/references/anonymous-apex-guide.md +0 -98
  1239. package/skills/handling-sf-data/references/bulk-operations-guide.md +0 -94
  1240. package/skills/handling-sf-data/references/bulk-testing-example.md +0 -194
  1241. package/skills/handling-sf-data/references/cleanup-rollback-example.md +0 -322
  1242. package/skills/handling-sf-data/references/cleanup-rollback-guide.md +0 -84
  1243. package/skills/handling-sf-data/references/crud-workflow-example.md +0 -183
  1244. package/skills/handling-sf-data/references/governor-limits-reference.md +0 -74
  1245. package/skills/handling-sf-data/references/orchestration.md +0 -174
  1246. package/skills/handling-sf-data/references/relationship-query-examples.md +0 -249
  1247. package/skills/handling-sf-data/references/sf-cli-data-commands.md +0 -158
  1248. package/skills/handling-sf-data/references/soql-relationship-guide.md +0 -84
  1249. package/skills/handling-sf-data/references/test-data-best-practices.md +0 -104
  1250. package/skills/handling-sf-data/references/test-data-factory-usage.md +0 -290
  1251. package/skills/handling-sf-data/references/test-data-patterns.md +0 -98
  1252. package/skills/handling-sf-data/scripts/soql_validator.py +0 -292
  1253. package/skills/handling-sf-data/scripts/validate_data_operation.py +0 -379
  1254. package/skills/harmonizing-datacloud/CREDITS.md +0 -3
  1255. package/skills/harmonizing-datacloud/README.md +0 -31
  1256. package/skills/harmonizing-datacloud/SKILL.md +0 -116
  1257. package/skills/implementing-ui-bundle-agentforce-conversation-client/SKILL.md +0 -280
  1258. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/agent-id-resolution.md +0 -46
  1259. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/constraints.md +0 -134
  1260. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/examples.md +0 -132
  1261. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/style-tokens.md +0 -260
  1262. package/skills/implementing-ui-bundle-agentforce-conversation-client/references/troubleshooting.md +0 -57
  1263. package/skills/implementing-ui-bundle-file-upload/SKILL.md +0 -398
  1264. package/skills/integrating-b2b-commerce-open-code-components/SKILL.md +0 -165
  1265. package/skills/investigating-agentforce-architecture/README.md +0 -156
  1266. package/skills/investigating-agentforce-architecture/SKILL.md +0 -230
  1267. package/skills/investigating-agentforce-architecture/assets/cli/describe_sobject.yaml +0 -16
  1268. package/skills/investigating-agentforce-architecture/assets/cli/describe_tooling_sobject.yaml +0 -17
  1269. package/skills/investigating-agentforce-architecture/assets/cli/list_metadata_genaiprompttemplate.yaml +0 -17
  1270. package/skills/investigating-agentforce-architecture/assets/cli/org_display.yaml +0 -15
  1271. package/skills/investigating-agentforce-architecture/assets/cli/retrieve_genai_plugin.yaml +0 -18
  1272. package/skills/investigating-agentforce-architecture/assets/cli/show_access_token.yaml +0 -27
  1273. package/skills/investigating-agentforce-architecture/assets/mermaid/action_tree.mmd +0 -20
  1274. package/skills/investigating-agentforce-architecture/assets/mermaid/data_flow.mmd +0 -19
  1275. package/skills/investigating-agentforce-architecture/assets/mermaid/dependency_graph.mmd +0 -19
  1276. package/skills/investigating-agentforce-architecture/assets/mermaid/invocation_sequence.mmd +0 -20
  1277. package/skills/investigating-agentforce-architecture/assets/mermaid/planner_state.mmd +0 -18
  1278. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_ids.soql +0 -3
  1279. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_names.soql +0 -3
  1280. package/skills/investigating-agentforce-architecture/assets/soql/bot_definition_details.soql +0 -3
  1281. package/skills/investigating-agentforce-architecture/assets/soql/bot_version_lookup.soql +0 -4
  1282. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_by_ids.soql +0 -3
  1283. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_ids_by_names.soql +0 -3
  1284. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_view_by_durable_ids.soql +0 -4
  1285. package/skills/investigating-agentforce-architecture/assets/soql/flow_metadata_by_id.soql +0 -3
  1286. package/skills/investigating-agentforce-architecture/assets/soql/functions_by_plugins.soql +0 -5
  1287. package/skills/investigating-agentforce-architecture/assets/soql/planner_attrs_by_parent_ids.soql +0 -3
  1288. package/skills/investigating-agentforce-architecture/assets/soql/planner_bundle_functions.soql +0 -3
  1289. package/skills/investigating-agentforce-architecture/assets/soql/planner_definition_by_agent_chain.soql +0 -3
  1290. package/skills/investigating-agentforce-architecture/assets/soql/plugin_functions_by_plugin_ids.soql +0 -3
  1291. package/skills/investigating-agentforce-architecture/assets/soql/plugin_instructions_by_plugin_ids.soql +0 -3
  1292. package/skills/investigating-agentforce-architecture/assets/soql/plugins_by_planner.soql +0 -4
  1293. package/skills/investigating-agentforce-architecture/references/architecture_sections.md +0 -243
  1294. package/skills/investigating-agentforce-architecture/references/contract.json +0 -244
  1295. package/skills/investigating-agentforce-architecture/references/soql_fields.md +0 -512
  1296. package/skills/investigating-agentforce-architecture/scripts/_shared/__init__.py +0 -1
  1297. package/skills/investigating-agentforce-architecture/scripts/_shared/fs_guard.py +0 -329
  1298. package/skills/investigating-agentforce-architecture/scripts/_shared/paths.py +0 -110
  1299. package/skills/investigating-agentforce-architecture/scripts/_shared/runtime.py +0 -59
  1300. package/skills/investigating-agentforce-architecture/scripts/_shared/sql.py +0 -10
  1301. package/skills/investigating-agentforce-architecture/scripts/cache_check.py +0 -234
  1302. package/skills/investigating-agentforce-architecture/scripts/config.py +0 -131
  1303. package/skills/investigating-agentforce-architecture/scripts/fetch_soql.py +0 -689
  1304. package/skills/investigating-agentforce-architecture/scripts/finalize.py +0 -295
  1305. package/skills/investigating-agentforce-architecture/scripts/main.py +0 -2835
  1306. package/skills/investigating-agentforce-architecture/scripts/metadata_listing.py +0 -265
  1307. package/skills/investigating-agentforce-architecture/scripts/parallel_retrieve.py +0 -69
  1308. package/skills/investigating-agentforce-architecture/scripts/parse_bundle.py +0 -215
  1309. package/skills/investigating-agentforce-architecture/scripts/parse_wave.py +0 -845
  1310. package/skills/investigating-agentforce-architecture/scripts/probe_channels.py +0 -302
  1311. package/skills/investigating-agentforce-architecture/scripts/render_architecture.py +0 -1043
  1312. package/skills/investigating-agentforce-architecture/scripts/resolve_bot.py +0 -255
  1313. package/skills/investigating-agentforce-architecture/scripts/resolve_invocation_target.py +0 -130
  1314. package/skills/investigating-agentforce-architecture/scripts/rest_client.py +0 -763
  1315. package/skills/investigating-agentforce-architecture/scripts/retrieve_planner.py +0 -13
  1316. package/skills/investigating-agentforce-architecture/scripts/sf_cli.py +0 -242
  1317. package/skills/investigating-agentforce-architecture/scripts/soql_loader.py +0 -253
  1318. package/skills/investigating-agentforce-architecture/scripts/summarize_tree.py +0 -143
  1319. package/skills/investigating-agentforce-architecture/scripts/tests/__init__.py +0 -0
  1320. package/skills/investigating-agentforce-architecture/scripts/tests/_bootstrap.py +0 -23
  1321. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/__init__.py +0 -0
  1322. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/genai_payloads.py +0 -400
  1323. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check.py +0 -307
  1324. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check_main.py +0 -283
  1325. package/skills/investigating-agentforce-architecture/scripts/tests/test_config.py +0 -115
  1326. package/skills/investigating-agentforce-architecture/scripts/tests/test_end_to_end_fixture.py +0 -651
  1327. package/skills/investigating-agentforce-architecture/scripts/tests/test_finalize.py +0 -278
  1328. package/skills/investigating-agentforce-architecture/scripts/tests/test_flow_children_inflation.py +0 -582
  1329. package/skills/investigating-agentforce-architecture/scripts/tests/test_fs_guard.py +0 -113
  1330. package/skills/investigating-agentforce-architecture/scripts/tests/test_iterative_wave_b.py +0 -478
  1331. package/skills/investigating-agentforce-architecture/scripts/tests/test_main_pipeline.py +0 -3359
  1332. package/skills/investigating-agentforce-architecture/scripts/tests/test_parallel_retrieve.py +0 -131
  1333. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_bundle.py +0 -400
  1334. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave.py +0 -644
  1335. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_classifiers.py +0 -224
  1336. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_helpers.py +0 -380
  1337. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_main.py +0 -397
  1338. package/skills/investigating-agentforce-architecture/scripts/tests/test_per_branch_visited.py +0 -244
  1339. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_channels.py +0 -359
  1340. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_cli_recipes.py +0 -185
  1341. package/skills/investigating-agentforce-architecture/scripts/tests/test_render_architecture.py +0 -810
  1342. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_bot.py +0 -203
  1343. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_creds.py +0 -157
  1344. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py +0 -145
  1345. package/skills/investigating-agentforce-architecture/scripts/tests/test_rest_client.py +0 -1253
  1346. package/skills/investigating-agentforce-architecture/scripts/tests/test_runtime_override.py +0 -100
  1347. package/skills/investigating-agentforce-architecture/scripts/tests/test_sf_cli.py +0 -261
  1348. package/skills/investigating-agentforce-architecture/scripts/tests/test_signature_stamping.py +0 -466
  1349. package/skills/investigating-agentforce-architecture/scripts/tests/test_soql_loader.py +0 -501
  1350. package/skills/investigating-agentforce-architecture/scripts/tests/test_summarize_tree.py +0 -241
  1351. package/skills/investigating-agentforce-architecture/scripts/tests/test_write_emit_ctx.py +0 -480
  1352. package/skills/investigating-agentforce-architecture/tools/emit_env.py +0 -157
  1353. package/skills/investigating-agentforce-architecture/tools/emit_result.py +0 -262
  1354. package/skills/investigating-agentforce-architecture/tools/sanitize.py +0 -33
  1355. package/skills/investigating-agentforce-architecture/tools/write_emit_ctx.py +0 -332
  1356. package/skills/investigating-agentforce-d360/README.md +0 -123
  1357. package/skills/investigating-agentforce-d360/SKILL.md +0 -163
  1358. package/skills/investigating-agentforce-d360/assets/dc/app_generation.sql +0 -51
  1359. package/skills/investigating-agentforce-d360/assets/dc/content_category.sql +0 -44
  1360. package/skills/investigating-agentforce-d360/assets/dc/content_quality.sql +0 -41
  1361. package/skills/investigating-agentforce-d360/assets/dc/discover_sessions.sql +0 -36
  1362. package/skills/investigating-agentforce-d360/assets/dc/feedback.sql +0 -47
  1363. package/skills/investigating-agentforce-d360/assets/dc/feedback_details.sql +0 -38
  1364. package/skills/investigating-agentforce-d360/assets/dc/gateway_records.sql +0 -45
  1365. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_llm.sql +0 -50
  1366. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_metadata.sql +0 -44
  1367. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_tags.sql +0 -42
  1368. package/skills/investigating-agentforce-d360/assets/dc/gateway_requests.sql +0 -89
  1369. package/skills/investigating-agentforce-d360/assets/dc/gateway_responses.sql +0 -43
  1370. package/skills/investigating-agentforce-d360/assets/dc/generations.sql +0 -52
  1371. package/skills/investigating-agentforce-d360/assets/dc/interactions.sql +0 -53
  1372. package/skills/investigating-agentforce-d360/assets/dc/messages.sql +0 -53
  1373. package/skills/investigating-agentforce-d360/assets/dc/messaging_session.sql +0 -37
  1374. package/skills/investigating-agentforce-d360/assets/dc/moment_interactions.sql +0 -34
  1375. package/skills/investigating-agentforce-d360/assets/dc/moments.sql +0 -39
  1376. package/skills/investigating-agentforce-d360/assets/dc/participants.sql +0 -48
  1377. package/skills/investigating-agentforce-d360/assets/dc/sessions.sql +0 -78
  1378. package/skills/investigating-agentforce-d360/assets/dc/steps.sql +0 -64
  1379. package/skills/investigating-agentforce-d360/assets/dc/tag_associations.sql +0 -46
  1380. package/skills/investigating-agentforce-d360/assets/dc/tag_definition_associations.sql +0 -37
  1381. package/skills/investigating-agentforce-d360/assets/dc/tag_definitions.sql +0 -50
  1382. package/skills/investigating-agentforce-d360/assets/dc/tags.sql +0 -37
  1383. package/skills/investigating-agentforce-d360/assets/dc/telemetry_spans.sql +0 -55
  1384. package/skills/investigating-agentforce-d360/references/artifacts.md +0 -50
  1385. package/skills/investigating-agentforce-d360/references/dc_dmo_fields.md +0 -823
  1386. package/skills/investigating-agentforce-d360/references/dc_pipeline_contract.md +0 -608
  1387. package/skills/investigating-agentforce-d360/scripts/_shared/__init__.py +0 -2
  1388. package/skills/investigating-agentforce-d360/scripts/_shared/cli_override.py +0 -98
  1389. package/skills/investigating-agentforce-d360/scripts/_shared/fs_guard.py +0 -334
  1390. package/skills/investigating-agentforce-d360/scripts/_shared/paths.py +0 -155
  1391. package/skills/investigating-agentforce-d360/scripts/_shared/runtime.py +0 -59
  1392. package/skills/investigating-agentforce-d360/scripts/_shared/sql.py +0 -14
  1393. package/skills/investigating-agentforce-d360/scripts/assemble_dc.py +0 -1624
  1394. package/skills/investigating-agentforce-d360/scripts/config.py +0 -45
  1395. package/skills/investigating-agentforce-d360/scripts/dc.py +0 -188
  1396. package/skills/investigating-agentforce-d360/scripts/discover_sessions.py +0 -556
  1397. package/skills/investigating-agentforce-d360/scripts/fetch_dc.py +0 -1045
  1398. package/skills/investigating-agentforce-d360/scripts/render_dc.py +0 -1750
  1399. package/skills/investigating-agentforce-d360/scripts/resolve_session.py +0 -264
  1400. package/skills/investigating-agentforce-d360/scripts/storage.py +0 -92
  1401. package/skills/investigating-agentforce-d360/scripts/tests/__init__.py +0 -0
  1402. package/skills/investigating-agentforce-d360/scripts/tests/_bootstrap.py +0 -15
  1403. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/__init__.py +0 -0
  1404. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/synthetic_session.py +0 -424
  1405. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_bootstrap_and_mode.py +0 -115
  1406. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct.py +0 -220
  1407. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct_integration.py +0 -158
  1408. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_helpers.py +0 -287
  1409. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_integration.py +0 -247
  1410. package/skills/investigating-agentforce-d360/scripts/tests/test_dc_and_resolve_session.py +0 -433
  1411. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions.py +0 -458
  1412. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions_grep_ci.py +0 -193
  1413. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_helpers.py +0 -266
  1414. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_identity.py +0 -528
  1415. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_main.py +0 -251
  1416. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall.py +0 -229
  1417. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall_full.py +0 -283
  1418. package/skills/investigating-agentforce-d360/scripts/tests/test_identity_coherence.py +0 -327
  1419. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_branches.py +0 -256
  1420. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_gateway_direct.py +0 -130
  1421. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_helpers.py +0 -291
  1422. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_integration.py +0 -220
  1423. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_planner_llm_calls.py +0 -284
  1424. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_show_prompts_gating.py +0 -215
  1425. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_from_disk.py +0 -100
  1426. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_session_main.py +0 -149
  1427. package/skills/investigating-agentforce-d360/scripts/tests/test_runtime_override.py +0 -104
  1428. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape.py +0 -95
  1429. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape_dropped_by_stdm.py +0 -85
  1430. package/skills/managing-cdc-enablement/SKILL.md +0 -164
  1431. package/skills/managing-cdc-enablement/assets/PlatformEventChannel-template.xml +0 -5
  1432. package/skills/managing-cdc-enablement/assets/PlatformEventChannelMember-template.xml +0 -11
  1433. package/skills/managing-cdc-enablement/references/deploy-troubleshooting.md +0 -73
  1434. package/skills/managing-cdc-enablement/references/filter-expressions.md +0 -93
  1435. package/skills/managing-managed-event-subscription/SKILL.md +0 -152
  1436. package/skills/managing-managed-event-subscription/assets/managed-event-subscription-template.xml +0 -20
  1437. package/skills/managing-managed-event-subscription/references/delete-guide.md +0 -57
  1438. package/skills/managing-managed-event-subscription/references/topic-name-formats.md +0 -26
  1439. package/skills/managing-managed-event-subscription/references/update-constraints.md +0 -30
  1440. package/skills/modeling-omnistudio-epc-catalog/CREDITS.md +0 -14
  1441. package/skills/modeling-omnistudio-epc-catalog/README.md +0 -89
  1442. package/skills/modeling-omnistudio-epc-catalog/SKILL.md +0 -394
  1443. package/skills/modeling-omnistudio-epc-catalog/assets/attribute-assignment-template.json +0 -402
  1444. package/skills/modeling-omnistudio-epc-catalog/assets/compiled-attribute-overrides-template.json +0 -43
  1445. package/skills/modeling-omnistudio-epc-catalog/assets/completion-block-template.txt +0 -8
  1446. package/skills/modeling-omnistudio-epc-catalog/assets/decomposition-relationships-template.json +0 -233
  1447. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_AttributeAssignments.json +0 -514
  1448. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_CompiledAttributeOverrides.json +0 -21
  1449. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DataPack.json +0 -649
  1450. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_DecompositionRelationships.json +0 -200
  1451. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ObjectFieldAttributes.json +0 -138
  1452. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OrchestrationScenarios.json +0 -54
  1453. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_OverrideDefinitions.json +0 -266
  1454. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ParentKeys.json +0 -23
  1455. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PriceListEntries.json +0 -54
  1456. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_PricebookEntries.json +0 -35
  1457. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_ProductChildItems.json +0 -34
  1458. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-premium-fttc-simple-offer/Business-Internet-Premium-FTTC_RuleAssignments.json +0 -21
  1459. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_AttributeAssignments.json +0 -410
  1460. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DataPack.json +0 -535
  1461. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_DecompositionRelationships.json +0 -35
  1462. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ObjectFieldAttributes.json +0 -138
  1463. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_OrchestrationScenarios.json +0 -28
  1464. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ParentKeys.json +0 -23
  1465. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PriceListEntries.json +0 -220
  1466. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_PricebookEntries.json +0 -35
  1467. package/skills/modeling-omnistudio-epc-catalog/assets/examples/business-internet-pro-vpl-simple-offer/Business-Internet-Pro-VPL_ProductChildItems.json +0 -414
  1468. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_AttributeAssignments.json +0 -382
  1469. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DataPack.json +0 -565
  1470. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_DecompositionRelationships.json +0 -35
  1471. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ObjectFieldAttributes.json +0 -104
  1472. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_OrchestrationScenarios.json +0 -28
  1473. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ParentKeys.json +0 -13
  1474. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PriceListEntries.json +0 -106
  1475. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_PricebookEntries.json +0 -35
  1476. package/skills/modeling-omnistudio-epc-catalog/assets/examples/samsung-galaxy-s22-bundle/Samsung-Galaxy-S22-Bundle_ProductChildItems.json +0 -72
  1477. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_AttributeAssignments.json +0 -142
  1478. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DataPack.json +0 -377
  1479. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_DecompositionRelationships.json +0 -35
  1480. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ObjectFieldAttributes.json +0 -36
  1481. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ParentKeys.json +0 -8
  1482. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PriceListEntries.json +0 -54
  1483. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_PricebookEntries.json +0 -35
  1484. package/skills/modeling-omnistudio-epc-catalog/assets/examples/static-ip-simple-offer/Static-IP_ProductChildItems.json +0 -34
  1485. package/skills/modeling-omnistudio-epc-catalog/assets/object-field-attributes-template.json +0 -138
  1486. package/skills/modeling-omnistudio-epc-catalog/assets/orchestration-scenarios-template.json +0 -54
  1487. package/skills/modeling-omnistudio-epc-catalog/assets/override-definitions-template.json +0 -134
  1488. package/skills/modeling-omnistudio-epc-catalog/assets/parent-keys-template.json +0 -29
  1489. package/skills/modeling-omnistudio-epc-catalog/assets/price-list-entries-template.json +0 -158
  1490. package/skills/modeling-omnistudio-epc-catalog/assets/pricebook-entries-template.json +0 -35
  1491. package/skills/modeling-omnistudio-epc-catalog/assets/product-child-item-template.json +0 -338
  1492. package/skills/modeling-omnistudio-epc-catalog/assets/product2-offer-template.json +0 -527
  1493. package/skills/modeling-omnistudio-epc-catalog/examples/.gitkeep +0 -1
  1494. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_AttributeAssignments.json +0 -95
  1495. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_CompiledAttributeOverrides.json +0 -1
  1496. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DataPack.json +0 -214
  1497. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_DecompositionRelationships.json +0 -28
  1498. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ObjectFieldAttributes.json +0 -98
  1499. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OrchestrationScenarios.json +0 -22
  1500. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_OverrideDefinitions.json +0 -1
  1501. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ParentKeys.json +0 -13
  1502. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PriceListEntries.json +0 -35
  1503. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_PricebookEntries.json +0 -28
  1504. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/Business-Internet-Plus_ProductChildItems.json +0 -110
  1505. package/skills/modeling-omnistudio-epc-catalog/examples/business-internet-plus-bundle/TRANSCRIPT.md +0 -58
  1506. package/skills/modeling-omnistudio-epc-catalog/references/epc-field-guide.md +0 -90
  1507. package/skills/modeling-omnistudio-epc-catalog/references/naming-conventions.md +0 -80
  1508. package/skills/modeling-omnistudio-epc-catalog/references/scoring-model.md +0 -57
  1509. package/skills/modeling-omnistudio-epc-catalog/scripts/cli-validation-commands.sh +0 -19
  1510. package/skills/modeling-omnistudio-epc-catalog/scripts/sample-invocations.sh +0 -18
  1511. package/skills/observing-agentforce/SKILL.md +0 -366
  1512. package/skills/observing-agentforce/apex/AgentforceOptimizeService.cls +0 -1262
  1513. package/skills/observing-agentforce/apex/AgentforceOptimizeService.cls-meta.xml +0 -5
  1514. package/skills/observing-agentforce/references/improve-reference.md +0 -359
  1515. package/skills/observing-agentforce/references/issue-classification.md +0 -220
  1516. package/skills/observing-agentforce/references/reproduce-reference.md +0 -131
  1517. package/skills/observing-agentforce/references/stdm-queries.md +0 -373
  1518. package/skills/observing-agentforce/references/stdm-schema.md +0 -189
  1519. package/skills/orchestrating-datacloud/CREDITS.md +0 -15
  1520. package/skills/orchestrating-datacloud/README.md +0 -127
  1521. package/skills/orchestrating-datacloud/SKILL.md +0 -235
  1522. package/skills/orchestrating-datacloud/UPSTREAM.md +0 -45
  1523. package/skills/orchestrating-datacloud/assets/definitions/activation-target.template.json +0 -5
  1524. package/skills/orchestrating-datacloud/assets/definitions/activation.template.json +0 -7
  1525. package/skills/orchestrating-datacloud/assets/definitions/calculated-insight.template.json +0 -7
  1526. package/skills/orchestrating-datacloud/assets/definitions/data-action-target.template.json +0 -5
  1527. package/skills/orchestrating-datacloud/assets/definitions/data-action.template.json +0 -5
  1528. package/skills/orchestrating-datacloud/assets/definitions/data-graph.template.json +0 -21
  1529. package/skills/orchestrating-datacloud/assets/definitions/data-stream.template.json +0 -55
  1530. package/skills/orchestrating-datacloud/assets/definitions/dmo.template.json +0 -17
  1531. package/skills/orchestrating-datacloud/assets/definitions/identity-resolution.template.json +0 -30
  1532. package/skills/orchestrating-datacloud/assets/definitions/mapping.template.json +0 -14
  1533. package/skills/orchestrating-datacloud/assets/definitions/relationship.template.json +0 -12
  1534. package/skills/orchestrating-datacloud/assets/definitions/search-index.template.json +0 -9
  1535. package/skills/orchestrating-datacloud/assets/definitions/segment.template.json +0 -16
  1536. package/skills/orchestrating-datacloud/references/feature-readiness.md +0 -157
  1537. package/skills/orchestrating-datacloud/references/plugin-setup.md +0 -138
  1538. package/skills/orchestrating-datacloud/scripts/bootstrap-plugin.sh +0 -53
  1539. package/skills/orchestrating-datacloud/scripts/diagnose-org.mjs +0 -511
  1540. package/skills/orchestrating-datacloud/scripts/generate-manifest.mjs +0 -68
  1541. package/skills/orchestrating-datacloud/scripts/verify-plugin.sh +0 -58
  1542. package/skills/platform-agentexchange-partner-offers-enable/SKILL.md +0 -111
  1543. package/skills/platform-agentexchange-partner-offers-enable/assets/org-pref-template.md +0 -27
  1544. package/skills/platform-agentexchange-partner-offers-enable/examples/org-preference-settings.xml +0 -4
  1545. package/skills/preparing-datacloud/CREDITS.md +0 -7
  1546. package/skills/preparing-datacloud/README.md +0 -51
  1547. package/skills/preparing-datacloud/SKILL.md +0 -190
  1548. package/skills/preparing-datacloud/examples/ingestion-api/.env.example +0 -8
  1549. package/skills/preparing-datacloud/examples/ingestion-api/README.md +0 -48
  1550. package/skills/preparing-datacloud/examples/ingestion-api/send-data.py +0 -144
  1551. package/skills/querying-soql/CREDITS.md +0 -21
  1552. package/skills/querying-soql/README.md +0 -41
  1553. package/skills/querying-soql/SKILL.md +0 -142
  1554. package/skills/querying-soql/assets/aggregate-queries.soql +0 -242
  1555. package/skills/querying-soql/assets/basic-queries.soql +0 -188
  1556. package/skills/querying-soql/assets/bulkified-query-pattern.cls +0 -280
  1557. package/skills/querying-soql/assets/optimization-patterns.soql +0 -259
  1558. package/skills/querying-soql/assets/relationship-queries.soql +0 -203
  1559. package/skills/querying-soql/assets/selector-class.cls +0 -219
  1560. package/skills/querying-soql/references/anti-patterns.md +0 -348
  1561. package/skills/querying-soql/references/cli-commands.md +0 -358
  1562. package/skills/querying-soql/references/field-coverage-rules.md +0 -514
  1563. package/skills/querying-soql/references/query-optimization.md +0 -142
  1564. package/skills/querying-soql/references/selector-patterns.md +0 -479
  1565. package/skills/querying-soql/references/soql-reference.md +0 -227
  1566. package/skills/querying-soql/references/soql-syntax-reference.md +0 -208
  1567. package/skills/querying-soql/scripts/post-tool-validate.py +0 -322
  1568. package/skills/retrieving-datacloud/CREDITS.md +0 -7
  1569. package/skills/retrieving-datacloud/README.md +0 -44
  1570. package/skills/retrieving-datacloud/SKILL.md +0 -119
  1571. package/skills/retrieving-datacloud/examples/search-indexes/hybrid-structured.json +0 -44
  1572. package/skills/retrieving-datacloud/examples/search-indexes/vector-knowledge.json +0 -43
  1573. package/skills/reviewing-lwc-mobile-offline/SKILL.md +0 -167
  1574. package/skills/reviewing-lwc-mobile-offline/references/grounding.md +0 -7
  1575. package/skills/reviewing-lwc-mobile-offline/references/inline-graphql.md +0 -43
  1576. package/skills/reviewing-lwc-mobile-offline/references/komaci-eslint.md +0 -125
  1577. package/skills/reviewing-lwc-mobile-offline/references/lwc-if.md +0 -78
  1578. package/skills/reviewing-lwc-mobile-offline/scripts/komaci.config.mjs +0 -18
  1579. package/skills/reviewing-lwc-mobile-offline/scripts/package.json +0 -10
  1580. package/skills/reviewing-lwc-mobile-offline/scripts/run-komaci.sh +0 -69
  1581. package/skills/running-apex-tests/CREDITS.md +0 -22
  1582. package/skills/running-apex-tests/README.md +0 -94
  1583. package/skills/running-apex-tests/SKILL.md +0 -157
  1584. package/skills/running-apex-tests/assets/basic-test.cls +0 -169
  1585. package/skills/running-apex-tests/assets/bulk-test.cls +0 -255
  1586. package/skills/running-apex-tests/assets/dml-mock.cls +0 -339
  1587. package/skills/running-apex-tests/assets/mock-callout-test.cls +0 -353
  1588. package/skills/running-apex-tests/assets/stub-provider-example.cls +0 -364
  1589. package/skills/running-apex-tests/assets/test-data-factory.cls +0 -328
  1590. package/skills/running-apex-tests/hooks/scripts/parse-test-results.py +0 -364
  1591. package/skills/running-apex-tests/references/cli-commands.md +0 -289
  1592. package/skills/running-apex-tests/references/mocking-patterns.md +0 -500
  1593. package/skills/running-apex-tests/references/performance-optimization.md +0 -283
  1594. package/skills/running-apex-tests/references/test-fix-loop.md +0 -49
  1595. package/skills/running-apex-tests/references/test-patterns.md +0 -154
  1596. package/skills/running-apex-tests/references/testing-best-practices.md +0 -509
  1597. package/skills/running-code-analyzer/SKILL.md +0 -495
  1598. package/skills/running-code-analyzer/examples/README.md +0 -38
  1599. package/skills/running-code-analyzer/examples/basic-scan-output.json +0 -92
  1600. package/skills/running-code-analyzer/examples/command-variations.md +0 -333
  1601. package/skills/running-code-analyzer/examples/fix-application-before-after.md +0 -142
  1602. package/skills/running-code-analyzer/examples/large-scan-output.json +0 -67
  1603. package/skills/running-code-analyzer/examples/security-focused-output.json +0 -95
  1604. package/skills/running-code-analyzer/references/command-examples.md +0 -27
  1605. package/skills/running-code-analyzer/references/engine-reference.md +0 -34
  1606. package/skills/running-code-analyzer/references/error-handling.md +0 -29
  1607. package/skills/running-code-analyzer/references/flag-reference.md +0 -96
  1608. package/skills/running-code-analyzer/references/post-scan-workflows.md +0 -286
  1609. package/skills/running-code-analyzer/references/quick-start.md +0 -28
  1610. package/skills/running-code-analyzer/references/special-behaviors.md +0 -83
  1611. package/skills/running-code-analyzer/references/vendor-file-handling.md +0 -239
  1612. package/skills/running-code-analyzer/scripts/apply-fixes.js +0 -86
  1613. package/skills/running-code-analyzer/scripts/describe-rule.js +0 -382
  1614. package/skills/running-code-analyzer/scripts/discover-fixes.js +0 -34
  1615. package/skills/running-code-analyzer/scripts/filter-violations.js +0 -405
  1616. package/skills/running-code-analyzer/scripts/list-rules.js +0 -260
  1617. package/skills/running-code-analyzer/scripts/parse-results.js +0 -59
  1618. package/skills/running-code-analyzer/scripts/query-results.js +0 -230
  1619. package/skills/running-code-analyzer/scripts/summarize-fixes.js +0 -32
  1620. package/skills/running-code-analyzer/scripts/verify-execution.sh +0 -28
  1621. package/skills/searching-media/SKILL.md +0 -348
  1622. package/skills/segmenting-datacloud/CREDITS.md +0 -3
  1623. package/skills/segmenting-datacloud/README.md +0 -36
  1624. package/skills/segmenting-datacloud/SKILL.md +0 -114
  1625. package/skills/switching-org/SKILL.md +0 -28
  1626. package/skills/testing-agentforce/SKILL.md +0 -333
  1627. package/skills/testing-agentforce/assets/basic-test-spec.yaml +0 -63
  1628. package/skills/testing-agentforce/assets/guardrail-test-spec.yaml +0 -105
  1629. package/skills/testing-agentforce/assets/standard-test-spec.yaml +0 -127
  1630. package/skills/testing-agentforce/references/action-execution.md +0 -241
  1631. package/skills/testing-agentforce/references/batch-testing.md +0 -274
  1632. package/skills/testing-agentforce/references/preview-testing.md +0 -353
  1633. package/skills/testing-agentforce/references/test-report-format.md +0 -160
  1634. package/skills/testing-agentforce/references/troubleshooting.md +0 -73
  1635. package/skills/uplifting-components-to-slds2/SKILL.md +0 -239
  1636. package/skills/uplifting-components-to-slds2/references/color-hooks-decision-guide.md +0 -459
  1637. package/skills/uplifting-components-to-slds2/references/common-patterns.md +0 -87
  1638. package/skills/uplifting-components-to-slds2/references/examples.md +0 -461
  1639. package/skills/uplifting-components-to-slds2/references/migration-checklist.md +0 -67
  1640. package/skills/uplifting-components-to-slds2/references/non-color-hooks-decision-guide.md +0 -333
  1641. package/skills/uplifting-components-to-slds2/references/rule-lwc-token-to-slds-hook.md +0 -135
  1642. package/skills/uplifting-components-to-slds2/references/rule-no-deprecated-tokens-slds1.md +0 -211
  1643. package/skills/uplifting-components-to-slds2/references/rule-no-hardcoded-values.md +0 -160
  1644. package/skills/uplifting-components-to-slds2/references/rule-no-slds-class-overrides.md +0 -126
  1645. package/skills/using-mobile-native-capabilities/SKILL.md +0 -181
  1646. package/skills/using-mobile-native-capabilities/references/app-review.md +0 -68
  1647. package/skills/using-mobile-native-capabilities/references/ar-space-capture.md +0 -125
  1648. package/skills/using-mobile-native-capabilities/references/barcode-scanner.md +0 -219
  1649. package/skills/using-mobile-native-capabilities/references/base-capability.md +0 -22
  1650. package/skills/using-mobile-native-capabilities/references/biometrics.md +0 -90
  1651. package/skills/using-mobile-native-capabilities/references/calendar.md +0 -213
  1652. package/skills/using-mobile-native-capabilities/references/contacts.md +0 -232
  1653. package/skills/using-mobile-native-capabilities/references/document-scanner.md +0 -342
  1654. package/skills/using-mobile-native-capabilities/references/geofencing.md +0 -123
  1655. package/skills/using-mobile-native-capabilities/references/location.md +0 -158
  1656. package/skills/using-mobile-native-capabilities/references/mobile-capabilities.md +0 -30
  1657. package/skills/using-mobile-native-capabilities/references/nfc.md +0 -181
  1658. package/skills/using-mobile-native-capabilities/references/payments.md +0 -95
  1659. package/skills/using-salesforce-archive/SKILL.md +0 -121
  1660. package/skills/using-salesforce-archive/examples/monitor-failed-jobs.md +0 -47
  1661. package/skills/using-salesforce-archive/references/archive-activity-entity.md +0 -59
  1662. package/skills/using-salesforce-archive/references/connect-api-operations.md +0 -157
  1663. package/skills/using-ui-bundle-salesforce-data/SKILL.md +0 -638
  1664. package/skills/using-ui-bundle-salesforce-data/scripts/graphql-search.sh +0 -191
  1665. package/skills/validating-slds/SKILL.md +0 -262
  1666. package/skills/validating-slds/references/quality-checks.md +0 -308
  1667. package/skills/validating-slds/references/report-format.md +0 -302
  1668. package/skills/validating-slds/scripts/analyze-quality.cjs +0 -521
@@ -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()