scc-universal 1.1.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 (271) hide show
  1. package/.claude-plugin/plugin.json +44 -0
  2. package/.cursor/agents/deep-researcher.md +142 -0
  3. package/.cursor/agents/doc-updater.md +219 -0
  4. package/.cursor/agents/eval-runner.md +335 -0
  5. package/.cursor/agents/learning-engine.md +210 -0
  6. package/.cursor/agents/loop-operator.md +245 -0
  7. package/.cursor/agents/refactor-cleaner.md +119 -0
  8. package/.cursor/agents/sf-admin-agent.md +127 -0
  9. package/.cursor/agents/sf-agentforce-agent.md +126 -0
  10. package/.cursor/agents/sf-apex-agent.md +117 -0
  11. package/.cursor/agents/sf-architect.md +426 -0
  12. package/.cursor/agents/sf-aura-reviewer.md +369 -0
  13. package/.cursor/agents/sf-bugfix-agent.md +101 -0
  14. package/.cursor/agents/sf-flow-agent.md +155 -0
  15. package/.cursor/agents/sf-integration-agent.md +141 -0
  16. package/.cursor/agents/sf-lwc-agent.md +123 -0
  17. package/.cursor/agents/sf-review-agent.md +357 -0
  18. package/.cursor/agents/sf-visualforce-reviewer.md +465 -0
  19. package/.cursor/hooks/adapter.js +81 -0
  20. package/.cursor/hooks/after-file-edit.js +26 -0
  21. package/.cursor/hooks/after-mcp-execution.js +12 -0
  22. package/.cursor/hooks/after-shell-execution.js +30 -0
  23. package/.cursor/hooks/after-tab-file-edit.js +12 -0
  24. package/.cursor/hooks/before-mcp-execution.js +11 -0
  25. package/.cursor/hooks/before-read-file.js +13 -0
  26. package/.cursor/hooks/before-shell-execution.js +29 -0
  27. package/.cursor/hooks/before-submit-prompt.js +23 -0
  28. package/.cursor/hooks/pre-compact.js +7 -0
  29. package/.cursor/hooks/session-end.js +10 -0
  30. package/.cursor/hooks/session-start.js +10 -0
  31. package/.cursor/hooks/stop.js +18 -0
  32. package/.cursor/hooks/subagent-start.js +10 -0
  33. package/.cursor/hooks/subagent-stop.js +10 -0
  34. package/.cursor/hooks.json +107 -0
  35. package/.cursor/skills/aside/SKILL.md +115 -0
  36. package/.cursor/skills/checkpoint/SKILL.md +50 -0
  37. package/.cursor/skills/configure-scc/SKILL.md +160 -0
  38. package/.cursor/skills/continuous-agent-loop/SKILL.md +260 -0
  39. package/.cursor/skills/mcp-server-patterns/SKILL.md +142 -0
  40. package/.cursor/skills/model-route/SKILL.md +81 -0
  41. package/.cursor/skills/prompt-optimizer/SKILL.md +366 -0
  42. package/.cursor/skills/refactor-clean/SKILL.md +133 -0
  43. package/.cursor/skills/resume-session/SKILL.md +111 -0
  44. package/.cursor/skills/save-session/SKILL.md +183 -0
  45. package/.cursor/skills/search-first/SKILL.md +140 -0
  46. package/.cursor/skills/security-scan/SKILL.md +142 -0
  47. package/.cursor/skills/sessions/SKILL.md +124 -0
  48. package/.cursor/skills/sf-agentforce-development/SKILL.md +449 -0
  49. package/.cursor/skills/sf-apex-async-patterns/SKILL.md +324 -0
  50. package/.cursor/skills/sf-apex-best-practices/SKILL.md +421 -0
  51. package/.cursor/skills/sf-apex-constraints/SKILL.md +79 -0
  52. package/.cursor/skills/sf-apex-cursor/SKILL.md +336 -0
  53. package/.cursor/skills/sf-apex-enterprise-patterns/SKILL.md +344 -0
  54. package/.cursor/skills/sf-apex-testing/SKILL.md +407 -0
  55. package/.cursor/skills/sf-api-design/SKILL.md +237 -0
  56. package/.cursor/skills/sf-approval-processes/SKILL.md +312 -0
  57. package/.cursor/skills/sf-aura-development/SKILL.md +260 -0
  58. package/.cursor/skills/sf-build-fix/SKILL.md +120 -0
  59. package/.cursor/skills/sf-data-modeling/SKILL.md +274 -0
  60. package/.cursor/skills/sf-debugging/SKILL.md +362 -0
  61. package/.cursor/skills/sf-deployment/SKILL.md +291 -0
  62. package/.cursor/skills/sf-deployment-constraints/SKILL.md +153 -0
  63. package/.cursor/skills/sf-devops-ci-cd/SKILL.md +322 -0
  64. package/.cursor/skills/sf-docs-lookup/SKILL.md +100 -0
  65. package/.cursor/skills/sf-e2e-testing/SKILL.md +321 -0
  66. package/.cursor/skills/sf-experience-cloud/SKILL.md +248 -0
  67. package/.cursor/skills/sf-flow-development/SKILL.md +376 -0
  68. package/.cursor/skills/sf-governor-limits/SKILL.md +319 -0
  69. package/.cursor/skills/sf-harness-audit/SKILL.md +139 -0
  70. package/.cursor/skills/sf-help/SKILL.md +156 -0
  71. package/.cursor/skills/sf-integration/SKILL.md +479 -0
  72. package/.cursor/skills/sf-lwc-constraints/SKILL.md +128 -0
  73. package/.cursor/skills/sf-lwc-development/SKILL.md +302 -0
  74. package/.cursor/skills/sf-lwc-testing/SKILL.md +387 -0
  75. package/.cursor/skills/sf-metadata-management/SKILL.md +285 -0
  76. package/.cursor/skills/sf-platform-events-cdc/SKILL.md +372 -0
  77. package/.cursor/skills/sf-quickstart/SKILL.md +170 -0
  78. package/.cursor/skills/sf-security/SKILL.md +330 -0
  79. package/.cursor/skills/sf-security-constraints/SKILL.md +125 -0
  80. package/.cursor/skills/sf-soql-constraints/SKILL.md +129 -0
  81. package/.cursor/skills/sf-soql-optimization/SKILL.md +353 -0
  82. package/.cursor/skills/sf-tdd-workflow/SKILL.md +332 -0
  83. package/.cursor/skills/sf-testing-constraints/SKILL.md +198 -0
  84. package/.cursor/skills/sf-trigger-constraints/SKILL.md +88 -0
  85. package/.cursor/skills/sf-trigger-frameworks/SKILL.md +343 -0
  86. package/.cursor/skills/sf-visualforce-development/SKILL.md +259 -0
  87. package/.cursor/skills/strategic-compact/SKILL.md +205 -0
  88. package/.cursor/skills/update-docs/SKILL.md +162 -0
  89. package/.cursor/skills/update-platform-docs/SKILL.md +86 -0
  90. package/.cursor-plugin/plugin.json +26 -0
  91. package/LICENSE +21 -0
  92. package/README.md +522 -0
  93. package/agents/deep-researcher.md +145 -0
  94. package/agents/doc-updater.md +222 -0
  95. package/agents/eval-runner.md +340 -0
  96. package/agents/learning-engine.md +211 -0
  97. package/agents/loop-operator.md +247 -0
  98. package/agents/refactor-cleaner.md +122 -0
  99. package/agents/sf-admin-agent.md +131 -0
  100. package/agents/sf-agentforce-agent.md +132 -0
  101. package/agents/sf-apex-agent.md +124 -0
  102. package/agents/sf-architect.md +435 -0
  103. package/agents/sf-aura-reviewer.md +372 -0
  104. package/agents/sf-bugfix-agent.md +105 -0
  105. package/agents/sf-flow-agent.md +159 -0
  106. package/agents/sf-integration-agent.md +146 -0
  107. package/agents/sf-lwc-agent.md +127 -0
  108. package/agents/sf-review-agent.md +366 -0
  109. package/agents/sf-visualforce-reviewer.md +468 -0
  110. package/assets/logo.svg +18 -0
  111. package/docs/ARCHITECTURE.md +133 -0
  112. package/docs/authoring-guide.md +373 -0
  113. package/docs/hook-development.md +578 -0
  114. package/docs/token-optimization.md +139 -0
  115. package/docs/workflow-examples.md +645 -0
  116. package/examples/agentforce-action/README.md +227 -0
  117. package/examples/apex-trigger-handler/README.md +114 -0
  118. package/examples/devops-pipeline/README.md +325 -0
  119. package/examples/flow-automation/README.md +188 -0
  120. package/examples/integration-pattern/README.md +416 -0
  121. package/examples/lwc-component/README.md +180 -0
  122. package/examples/platform-events/README.md +492 -0
  123. package/examples/scratch-org-setup/README.md +138 -0
  124. package/examples/security-audit/README.md +244 -0
  125. package/examples/visualforce-migration/README.md +314 -0
  126. package/hooks/hooks.json +338 -0
  127. package/hooks/memory-persistence/README.md +73 -0
  128. package/manifests/install-modules.json +217 -0
  129. package/manifests/install-profiles.json +17 -0
  130. package/mcp-configs/mcp-servers.json +19 -0
  131. package/package.json +89 -0
  132. package/schemas/hooks.schema.json +123 -0
  133. package/schemas/install-modules.schema.json +76 -0
  134. package/schemas/install-profiles.schema.json +28 -0
  135. package/schemas/install-state.schema.json +73 -0
  136. package/schemas/package-manager.schema.json +18 -0
  137. package/schemas/plugin.schema.json +112 -0
  138. package/schemas/scc-install-config.schema.json +29 -0
  139. package/schemas/state-store.schema.json +111 -0
  140. package/scripts/cli/install-apply.js +170 -0
  141. package/scripts/cli/uninstall.js +193 -0
  142. package/scripts/hooks/check-console-log.js +101 -0
  143. package/scripts/hooks/check-hook-enabled.js +17 -0
  144. package/scripts/hooks/check-platform-docs-age.js +48 -0
  145. package/scripts/hooks/cost-tracker.js +78 -0
  146. package/scripts/hooks/doc-file-warning.js +63 -0
  147. package/scripts/hooks/evaluate-session.js +98 -0
  148. package/scripts/hooks/governor-check.js +220 -0
  149. package/scripts/hooks/learning-observe.sh +206 -0
  150. package/scripts/hooks/mcp-health-check.js +588 -0
  151. package/scripts/hooks/post-bash-build-complete.js +34 -0
  152. package/scripts/hooks/post-bash-pr-created.js +43 -0
  153. package/scripts/hooks/post-edit-console-warn.js +61 -0
  154. package/scripts/hooks/post-edit-format.js +79 -0
  155. package/scripts/hooks/post-edit-typecheck.js +98 -0
  156. package/scripts/hooks/post-write.js +168 -0
  157. package/scripts/hooks/pre-bash-git-push-reminder.js +35 -0
  158. package/scripts/hooks/pre-bash-tmux-reminder.js +47 -0
  159. package/scripts/hooks/pre-compact.js +51 -0
  160. package/scripts/hooks/pre-tool-use.js +163 -0
  161. package/scripts/hooks/pre-write-doc-warn.js +9 -0
  162. package/scripts/hooks/quality-gate.js +251 -0
  163. package/scripts/hooks/run-with-flags-shell.sh +32 -0
  164. package/scripts/hooks/run-with-flags.js +135 -0
  165. package/scripts/hooks/session-end-marker.js +29 -0
  166. package/scripts/hooks/session-end.js +311 -0
  167. package/scripts/hooks/session-start.js +202 -0
  168. package/scripts/hooks/sfdx-scanner-check.js +142 -0
  169. package/scripts/hooks/sfdx-validate.js +119 -0
  170. package/scripts/hooks/stop-hook.js +170 -0
  171. package/scripts/hooks/suggest-compact.js +67 -0
  172. package/scripts/lib/agent-adapter.js +82 -0
  173. package/scripts/lib/apex-analysis.js +194 -0
  174. package/scripts/lib/hook-flags.js +74 -0
  175. package/scripts/lib/install-config.js +73 -0
  176. package/scripts/lib/install-executor.js +363 -0
  177. package/scripts/lib/install-state.js +121 -0
  178. package/scripts/lib/orchestration-session.js +299 -0
  179. package/scripts/lib/package-manager.js +124 -0
  180. package/scripts/lib/project-detect.js +228 -0
  181. package/scripts/lib/schema-validator.js +190 -0
  182. package/scripts/lib/skill-adapter.js +100 -0
  183. package/scripts/lib/state-store.js +376 -0
  184. package/scripts/lib/tmux-worktree-orchestrator.js +598 -0
  185. package/scripts/lib/utils.js +313 -0
  186. package/scripts/scc.js +164 -0
  187. package/skills/_reference/AGENTFORCE_PATTERNS.md +112 -0
  188. package/skills/_reference/APEX_CURSOR.md +159 -0
  189. package/skills/_reference/API_VERSIONS.md +78 -0
  190. package/skills/_reference/APPROVAL_PROCESSES.md +105 -0
  191. package/skills/_reference/ASYNC_PATTERNS.md +163 -0
  192. package/skills/_reference/AURA_COMPONENTS.md +146 -0
  193. package/skills/_reference/DATA_MIGRATION_PATTERNS.md +151 -0
  194. package/skills/_reference/DATA_MODELING.md +124 -0
  195. package/skills/_reference/DEBUGGING_TOOLS.md +140 -0
  196. package/skills/_reference/DEPLOYMENT_CHECKLIST.md +87 -0
  197. package/skills/_reference/DEPRECATIONS.md +79 -0
  198. package/skills/_reference/DOCKER_CI_PATTERNS.md +138 -0
  199. package/skills/_reference/ENTERPRISE_PATTERNS.md +122 -0
  200. package/skills/_reference/EXPERIENCE_CLOUD.md +143 -0
  201. package/skills/_reference/FLOW_PATTERNS.md +113 -0
  202. package/skills/_reference/GOVERNOR_LIMITS.md +77 -0
  203. package/skills/_reference/INTEGRATION_PATTERNS.md +105 -0
  204. package/skills/_reference/LWC_PATTERNS.md +79 -0
  205. package/skills/_reference/METADATA_TYPES.md +115 -0
  206. package/skills/_reference/NAMING_CONVENTIONS.md +84 -0
  207. package/skills/_reference/PACKAGE_DEVELOPMENT.md +150 -0
  208. package/skills/_reference/PLATFORM_EVENTS.md +121 -0
  209. package/skills/_reference/REPORTING_API.md +143 -0
  210. package/skills/_reference/SCRATCH_ORG_PATTERNS.md +126 -0
  211. package/skills/_reference/SECURITY_PATTERNS.md +127 -0
  212. package/skills/_reference/SHARING_MODEL.md +120 -0
  213. package/skills/_reference/SOQL_PATTERNS.md +119 -0
  214. package/skills/_reference/TESTING_STANDARDS.md +96 -0
  215. package/skills/_reference/TRIGGER_PATTERNS.md +114 -0
  216. package/skills/_reference/VISUALFORCE_PATTERNS.md +121 -0
  217. package/skills/aside/SKILL.md +118 -0
  218. package/skills/checkpoint/SKILL.md +53 -0
  219. package/skills/configure-scc/SKILL.md +163 -0
  220. package/skills/continuous-agent-loop/SKILL.md +264 -0
  221. package/skills/mcp-server-patterns/SKILL.md +146 -0
  222. package/skills/model-route/SKILL.md +84 -0
  223. package/skills/prompt-optimizer/SKILL.md +369 -0
  224. package/skills/refactor-clean/SKILL.md +136 -0
  225. package/skills/resume-session/SKILL.md +114 -0
  226. package/skills/save-session/SKILL.md +186 -0
  227. package/skills/search-first/SKILL.md +144 -0
  228. package/skills/security-scan/SKILL.md +146 -0
  229. package/skills/sessions/SKILL.md +127 -0
  230. package/skills/sf-agentforce-development/SKILL.md +450 -0
  231. package/skills/sf-apex-async-patterns/SKILL.md +326 -0
  232. package/skills/sf-apex-best-practices/SKILL.md +425 -0
  233. package/skills/sf-apex-constraints/SKILL.md +81 -0
  234. package/skills/sf-apex-cursor/SKILL.md +338 -0
  235. package/skills/sf-apex-enterprise-patterns/SKILL.md +348 -0
  236. package/skills/sf-apex-testing/SKILL.md +409 -0
  237. package/skills/sf-api-design/SKILL.md +238 -0
  238. package/skills/sf-approval-processes/SKILL.md +315 -0
  239. package/skills/sf-aura-development/SKILL.md +263 -0
  240. package/skills/sf-build-fix/SKILL.md +121 -0
  241. package/skills/sf-data-modeling/SKILL.md +278 -0
  242. package/skills/sf-debugging/SKILL.md +363 -0
  243. package/skills/sf-deployment/SKILL.md +295 -0
  244. package/skills/sf-deployment-constraints/SKILL.md +155 -0
  245. package/skills/sf-devops-ci-cd/SKILL.md +325 -0
  246. package/skills/sf-docs-lookup/SKILL.md +103 -0
  247. package/skills/sf-e2e-testing/SKILL.md +324 -0
  248. package/skills/sf-experience-cloud/SKILL.md +249 -0
  249. package/skills/sf-flow-development/SKILL.md +377 -0
  250. package/skills/sf-governor-limits/SKILL.md +323 -0
  251. package/skills/sf-harness-audit/SKILL.md +142 -0
  252. package/skills/sf-help/SKILL.md +159 -0
  253. package/skills/sf-integration/SKILL.md +483 -0
  254. package/skills/sf-lwc-constraints/SKILL.md +130 -0
  255. package/skills/sf-lwc-development/SKILL.md +303 -0
  256. package/skills/sf-lwc-testing/SKILL.md +388 -0
  257. package/skills/sf-metadata-management/SKILL.md +288 -0
  258. package/skills/sf-platform-events-cdc/SKILL.md +375 -0
  259. package/skills/sf-quickstart/SKILL.md +173 -0
  260. package/skills/sf-security/SKILL.md +334 -0
  261. package/skills/sf-security-constraints/SKILL.md +127 -0
  262. package/skills/sf-soql-constraints/SKILL.md +131 -0
  263. package/skills/sf-soql-optimization/SKILL.md +354 -0
  264. package/skills/sf-tdd-workflow/SKILL.md +336 -0
  265. package/skills/sf-testing-constraints/SKILL.md +200 -0
  266. package/skills/sf-trigger-constraints/SKILL.md +90 -0
  267. package/skills/sf-trigger-frameworks/SKILL.md +347 -0
  268. package/skills/sf-visualforce-development/SKILL.md +260 -0
  269. package/skills/strategic-compact/SKILL.md +208 -0
  270. package/skills/update-docs/SKILL.md +165 -0
  271. package/skills/update-platform-docs/SKILL.md +90 -0
@@ -0,0 +1,377 @@
1
+ ---
2
+ name: sf-flow-development
3
+ description: "Salesforce Flow development — flow types, patterns, bulkification, error handling, testing, subflows, Flow vs Apex. Use when building or reviewing Flows. Do NOT use for pure Apex or Platform Event architecture."
4
+ origin: SCC
5
+ user-invocable: false
6
+ ---
7
+
8
+ # Salesforce Flow Development
9
+
10
+ Procedures for building, testing, and maintaining Salesforce Flows. Flow type details, governor limits, bulkification rules, and the Flow vs Apex decision matrix live in the reference file.
11
+
12
+ @../_reference/FLOW_PATTERNS.md
13
+
14
+ ## When to Use
15
+
16
+ - Building or debugging Salesforce Flows (record-triggered, screen, scheduled, autolaunched, orchestration)
17
+ - Deciding between Flow and Apex for automation
18
+ - Configuring fault paths, bulkification, or governor-safe flow patterns
19
+ - Implementing subflows, versioning, or modular flow design
20
+ - Migrating from Process Builder to Record-Triggered Flows
21
+
22
+ ---
23
+
24
+ ## Before Save: Field Updates (Recommended Pattern)
25
+
26
+ ```
27
+ Flow: ACC_SetAccountPriority (Before Save, Account, before insert OR before update)
28
+ Entry Condition: {!$Record.AnnualRevenue} >= 1000000
29
+
30
+ Steps:
31
+ 1. Assignment: {!$Record.Priority__c} = "High"
32
+ 2. Assignment: {!$Record.Tier__c} = "Enterprise"
33
+
34
+ Notes:
35
+ - No Get Records, Update Records, or Create Records elements allowed
36
+ - No DML of any kind
37
+ - Very fast — runs in memory before DB write
38
+ ```
39
+
40
+ ## After Save: Related Record Creation
41
+
42
+ ```
43
+ Flow: OPP_CreateNegotiationTask (After Save, Opportunity, after update)
44
+ Entry Condition: {!$Record.StageName} = "Negotiation"
45
+ AND {!$Record.StageName} <> {!$Record__Prior.StageName}
46
+
47
+ Steps:
48
+ 1. Get Records: User WHERE Id = {!$Record.OwnerId}
49
+ 2. Create Records: Task (
50
+ Subject = "Review negotiation checklist"
51
+ WhatId = {!$Record.Id}
52
+ OwnerId = {!$Record.OwnerId}
53
+ ActivityDate = TODAY() + 3
54
+ Priority = "High"
55
+ )
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Before Save vs After Save Decision
61
+
62
+ ```
63
+ Need to update the SAME record's fields?
64
+ -> Before Save (no DML counted, faster)
65
+ Note: Before Save flows cannot use Get Records or DML elements,
66
+ but CAN access parent fields via cross-object formula references
67
+ (e.g., {!$Record.Account.Name}).
68
+
69
+ Need to create/update OTHER records?
70
+ -> After Save (can do DML on other objects)
71
+
72
+ Need to send emails or call external services?
73
+ -> After Save (outbound actions need committed record)
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Bulkification Patterns
79
+
80
+ ### DML Outside the Loop (Critical)
81
+
82
+ ```
83
+ BAD:
84
+ Loop: For each Contact in {!Contacts}
85
+ |
86
+ +-> Update Records: Contact <- DML inside loop = 1 DML per record
87
+
88
+ GOOD:
89
+ Loop: For each Contact in {!Contacts}
90
+ |
91
+ +-> Assignment: Add to contactsToUpdate collection
92
+
93
+ Update Records: {!contactsToUpdate} <- Single DML for entire collection
94
+ ```
95
+
96
+ ### SOQL Outside the Loop
97
+
98
+ ```
99
+ BAD:
100
+ Loop: For each Opportunity in {!Opportunities}
101
+ |
102
+ +-> Get Records: Account WHERE Id = {!loopVar.AccountId} <- SOQL per record
103
+
104
+ GOOD:
105
+ Get Records: Account WHERE Id IN {!opportunityAccountIds} <- single query
106
+
107
+ Loop: For each Opportunity in {!Opportunities}
108
+ |
109
+ +-> (Use data from pre-fetched collection, no SOQL)
110
+
111
+ Heap warning: If pre-fetch returns 10K+ records, the collection may
112
+ exceed the heap size limit (see @../_reference/GOVERNOR_LIMITS.md). Filter aggressively, or move to Batch Apex.
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Subflows: Modular Design
118
+
119
+ ```
120
+ Parent Flow: SCR_CustomerOnboarding (Screen Flow)
121
+ |
122
+ +-- Subflow: VAL_ValidateAddress (Autolaunched)
123
+ | Input: {!streetAddress}, {!city}, {!state}
124
+ | Output: {!isValidAddress}, {!normalizedAddress}
125
+ |
126
+ +-- Subflow: INT_CreateCRMAccount (Autolaunched)
127
+ | Input: {!accountData}
128
+ | Output: {!newAccountId}
129
+ |
130
+ +-- Subflow: NOT_SendWelcomeEmail (Autolaunched)
131
+ Input: {!accountId}, {!contactEmail}
132
+ ```
133
+
134
+ Variables passed between parent and subflow must be marked as available for input/output in the subflow definition.
135
+
136
+ ---
137
+
138
+ ## Error Handling: Fault Connectors
139
+
140
+ Every element that can fail should have a fault connector.
141
+
142
+ ```
143
+ [Update Records: Update Account]
144
+ |
145
+ +-(SUCCESS)-> [Next Step]
146
+ |
147
+ +-(FAULT)-> [Assignment: errorMessage =
148
+ "Failed: " + {!$Flow.FaultMessage}]
149
+ |
150
+ +-> [Screen: Display Error to User]
151
+ OR
152
+ +-> [Create Records: Error_Log__c]
153
+ OR
154
+ +-> [Custom Notification: Notify Admin]
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Get Records Best Practices
160
+
161
+ ```
162
+ Element: Get Records
163
+ Object: Contact
164
+ Filter: AccountId = {!$Record.Id} AND IsActive__c = true
165
+ Store All Records: No (when you need just one) / Yes (for a collection)
166
+
167
+ Tips:
168
+ - Add filter conditions to reduce records returned
169
+ - Select only the fields you need
170
+ - Use "Only the first record" when you need a single result
171
+ - Filter on indexed fields when possible (Id, OwnerId, ExternalId__c)
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Custom Labels and Custom Metadata in Flows
177
+
178
+ ### Custom Labels
179
+
180
+ ```
181
+ Formula Resource:
182
+ Name: FormattedMessage
183
+ Data Type: Text
184
+ Value: {!$Label.Welcome_Message} & " " & {!ContactRecord.FirstName}
185
+ ```
186
+
187
+ ### Custom Metadata Types
188
+
189
+ ```
190
+ Get Records:
191
+ Object: Service_Config__mdt
192
+ Filter: DeveloperName = "Production"
193
+ Fields: Endpoint_URL__c, Timeout_Ms__c
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Testing Flows
199
+
200
+ ### Apex Test Coverage for Record-Triggered Flows
201
+
202
+ ```apex
203
+ @IsTest
204
+ public class OppNegotiationFlowTest {
205
+
206
+ @TestSetup
207
+ static void setup() {
208
+ Account acc = TestDataFactory.createAccount('Test Account');
209
+ insert acc;
210
+ }
211
+
212
+ @IsTest
213
+ static void testNegotiationTask_stageChanged_createsTask() {
214
+ Account acc = [SELECT Id FROM Account LIMIT 1];
215
+
216
+ Opportunity opp = new Opportunity(
217
+ Name = 'Test Opp',
218
+ AccountId = acc.Id,
219
+ StageName = 'Prospecting',
220
+ CloseDate = Date.today().addDays(30),
221
+ Amount = 50000
222
+ );
223
+ insert opp;
224
+
225
+ Test.startTest();
226
+ opp.StageName = 'Negotiation';
227
+ update opp;
228
+ Test.stopTest();
229
+
230
+ List<Task> tasks = [SELECT Subject, Priority
231
+ FROM Task WHERE WhatId = :opp.Id];
232
+ System.assertEquals(1, tasks.size());
233
+ System.assertEquals('Review negotiation checklist', tasks[0].Subject);
234
+ }
235
+
236
+ @IsTest
237
+ static void testNegotiationTask_bulk_createsTasksForAll() {
238
+ Account acc = [SELECT Id FROM Account LIMIT 1];
239
+
240
+ List<Opportunity> opps = new List<Opportunity>();
241
+ for (Integer i = 0; i < 200; i++) {
242
+ opps.add(new Opportunity(
243
+ Name = 'Bulk Opp ' + i,
244
+ AccountId = acc.Id,
245
+ StageName = 'Prospecting',
246
+ CloseDate = Date.today().addDays(30),
247
+ Amount = 1000 * i
248
+ ));
249
+ }
250
+ insert opps;
251
+
252
+ Test.startTest();
253
+ for (Opportunity opp : opps) { opp.StageName = 'Negotiation'; }
254
+ update opps;
255
+ Test.stopTest();
256
+
257
+ Integer taskCount = [SELECT COUNT() FROM Task WHERE WhatId IN :opps];
258
+ System.assertEquals(200, taskCount);
259
+ }
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## New Screen Flow Components (Spring '26)
266
+
267
+ Five native Screen Flow components that eliminate the need for custom LWC in common patterns:
268
+
269
+ | Component | Best For |
270
+ |-----------|----------|
271
+ | **Kanban Board** | Stage/status reassignment wizards, visual prioritization |
272
+ | **Message** | Confirmation prompts, warnings before destructive steps |
273
+ | **File Preview** | Document review steps in approval flows |
274
+ | **Integrated Approval** | Wizard-based approval flows where reps submit and track |
275
+ | **Editable Data Table** | Mass-edit child records within a guided wizard |
276
+
277
+ ---
278
+
279
+ ## Record-Triggered Flows on Files (Spring '26)
280
+
281
+ Record-Triggered Flows now support `ContentVersion` as a triggering object.
282
+
283
+ ```
284
+ Object: ContentVersion
285
+ Trigger: A record is created or updated
286
+ Entry Conditions:
287
+ - {!$Record.FileExtension} = 'pdf'
288
+ - {!$Record.Title} Does NOT Contain 'DRAFT'
289
+
290
+ Use cases:
291
+ - Auto-tag documents based on filename patterns
292
+ - Notify a team when a contract document is uploaded
293
+ - Create audit log when a sensitive file type is uploaded
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Orchestration Flow Design
299
+
300
+ Orchestration Flows manage long-running, multi-step processes spanning hours or days.
301
+
302
+ ```
303
+ Orchestration Flow: Employee_Onboarding
304
+ +-- Stage 1: "System Setup"
305
+ | +-- Background Step: Create user account (Autolaunched Flow)
306
+ | +-- Background Step: Provision email (Autolaunched Flow)
307
+ +-- Stage 2: "HR Review"
308
+ | +-- Interactive Step: Complete onboarding form (Screen Flow -> HR Manager)
309
+ +-- Stage 3: "Equipment & Access"
310
+ | +-- Interactive Step: Order equipment (Screen Flow -> IT Team queue)
311
+ | +-- Background Step: Grant system permissions (Autolaunched Flow)
312
+ +-- Stage 4: "Orientation"
313
+ +-- Interactive Step: Schedule orientation (Screen Flow -> Employee)
314
+ ```
315
+
316
+ ### Key Design Principles
317
+
318
+ - Stages execute sequentially -- Stage 2 waits for all Stage 1 steps
319
+ - Steps within a stage can run in parallel
320
+ - Interactive steps pause the orchestration until the assigned user completes the Screen Flow
321
+ - Background steps run automatically using Autolaunched Flows
322
+ - Define fault paths on background steps to prevent stalled orchestrations
323
+
324
+ ---
325
+
326
+ ## Flow Versioning and Activation
327
+
328
+ ```
329
+ Each Flow has:
330
+ - Multiple versions (v1, v2, v3...)
331
+ - Only ONE active version at a time
332
+ - Inactive versions can be tested without activating
333
+
334
+ Deployment:
335
+ - Deploying creates a new version
336
+ - Set status: Active in Flow metadata to auto-activate:
337
+ ```
338
+
339
+ ```xml
340
+ <status>Active</status>
341
+ ```
342
+
343
+ ```bash
344
+ sf project deploy start \
345
+ --metadata "Flow:OPP_CreateNegotiationTask" \
346
+ --target-org myOrg
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Process Builder Migration
352
+
353
+ ```
354
+ 1. IDENTIFY — List all active Process Builders
355
+ sf data query -q "SELECT Id, MasterLabel, ProcessType FROM Flow
356
+ WHERE ProcessType = 'Workflow' AND Status = 'Active'" --json
357
+
358
+ 2. ANALYZE — Document trigger object, criteria, and actions
359
+
360
+ 3. CREATE — Build equivalent Record-Triggered Flow:
361
+ - Before Save Flow for field updates
362
+ - After Save Flow for create records, email alerts
363
+
364
+ 4. TEST — Deploy to sandbox, test with bulk data (200+ records)
365
+
366
+ 5. DEACTIVATE — Turn off Process Builder, monitor 1-2 weeks
367
+
368
+ 6. CLEANUP — Delete via destructiveChanges.xml
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Related
374
+
375
+ - Agent: `sf-flow-agent` -- for interactive, in-depth guidance
376
+ - Constraints: sf-apex-constraints (for Apex-invoked flows)
377
+ - Reference: @../_reference/FLOW_PATTERNS.md
@@ -0,0 +1,323 @@
1
+ ---
2
+ name: sf-governor-limits
3
+ description: >-
4
+ Use when hitting Salesforce governor limits in Apex — SOQL, DML, heap,
5
+ CPU optimization, async offloading, bulk processing strategies.
6
+ Do NOT use for general Apex or LWC patterns.
7
+ origin: SCC
8
+ user-invocable: false
9
+ ---
10
+
11
+ # Governor Limits — Working Within Limits
12
+
13
+ Salesforce governor limits prevent any single transaction from monopolizing shared infrastructure. Hitting a limit throws `System.LimitException`, which cannot be caught. This skill covers strategies and optimization procedures. See @../_reference/GOVERNOR_LIMITS.md for the complete limits reference table.
14
+
15
+ @../_reference/GOVERNOR_LIMITS.md
16
+
17
+ ## When to Use
18
+
19
+ - A transaction throws `System.LimitException` in production or tests
20
+ - Reviewing Apex code for SOQL/DML-in-loop anti-patterns before deployment
21
+ - Batch or trigger jobs intermittently hitting CPU or heap limits
22
+ - Profiling a large data operation processing 200+ records
23
+ - Optimizing a slow trigger handler or service class for bulk safety
24
+ - Preparing for an ISV security review that checks governor limit compliance
25
+
26
+ ## Checking Limits Programmatically
27
+
28
+ The `Limits` class provides real-time limit consumption. Use it defensively before expensive operations.
29
+
30
+ ```apex
31
+ public class LimitAwareProcessor {
32
+ public void processIfSafe(List<Account> accounts) {
33
+ Integer soqlRemaining = Limits.getLimitQueries() - Limits.getQueries();
34
+ if (soqlRemaining < 5) {
35
+ System.debug(LoggingLevel.WARN,
36
+ 'Low SOQL budget: ' + Limits.getQueries() + '/' +
37
+ Limits.getLimitQueries() + '. Deferring to async.');
38
+ if (Limits.getQueueableJobs() < Limits.getLimitQueueableJobs()
39
+ && !System.isBatch() && !System.isFuture()) {
40
+ System.enqueueJob(new AccountProcessorJob(extractIds(accounts)));
41
+ }
42
+ return;
43
+ }
44
+
45
+ Integer dmlRemaining = Limits.getLimitDmlStatements() - Limits.getDmlStatements();
46
+ if (dmlRemaining < 3) {
47
+ throw new LimitSafetyException(
48
+ 'Insufficient DML budget. ' +
49
+ Limits.getDmlStatements() + '/' + Limits.getLimitDmlStatements() + ' used.'
50
+ );
51
+ }
52
+
53
+ Integer heapUsed = Limits.getHeapSize();
54
+ Integer heapLimit = Limits.getLimitHeapSize();
55
+ if (heapUsed > heapLimit * 0.75) {
56
+ System.debug(LoggingLevel.WARN, 'Heap at 75% — skipping optional enrichment.');
57
+ }
58
+
59
+ processInternal(accounts);
60
+ }
61
+
62
+ public class LimitSafetyException extends Exception {}
63
+ }
64
+ ```
65
+
66
+ ---
67
+
68
+ ## SOQL Limit Strategies
69
+
70
+ ### Query Once, Store in Map
71
+
72
+ The most impactful single optimization in Salesforce development.
73
+
74
+ ```apex
75
+ public void processAccounts(List<Account> accounts) {
76
+ Set<Id> accountIds = new Set<Id>();
77
+ for (Account acc : accounts) accountIds.add(acc.Id);
78
+
79
+ Map<Id, List<Contact>> contactsByAccountId = new Map<Id, List<Contact>>();
80
+ for (Contact con : [SELECT Id, Email, AccountId FROM Contact WHERE AccountId IN :accountIds]) {
81
+ if (!contactsByAccountId.containsKey(con.AccountId)) {
82
+ contactsByAccountId.put(con.AccountId, new List<Contact>());
83
+ }
84
+ contactsByAccountId.get(con.AccountId).add(con);
85
+ }
86
+
87
+ for (Account acc : accounts) {
88
+ List<Contact> contacts = contactsByAccountId.get(acc.Id);
89
+ if (contacts != null) sendEmailsToContacts(contacts);
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Use Aggregate Queries
95
+
96
+ ```apex
97
+ // 1 query instead of 3
98
+ Map<String, Integer> countsByType = new Map<String, Integer>();
99
+ for (AggregateResult ar : [
100
+ SELECT Type, COUNT(Id) cnt FROM Account WHERE Type != null GROUP BY Type
101
+ ]) {
102
+ countsByType.put((String) ar.get('Type'), (Integer) ar.get('cnt'));
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## DML Limit Strategies
109
+
110
+ ### Collect Records, Single DML After Loop
111
+
112
+ ```apex
113
+ public void setDefaultTitle(List<Contact> contacts) {
114
+ List<Contact> toUpdate = new List<Contact>();
115
+ for (Contact con : contacts) {
116
+ if (String.isBlank(con.Title)) {
117
+ toUpdate.add(new Contact(Id = con.Id, Title = 'Business Contact'));
118
+ }
119
+ }
120
+ if (!toUpdate.isEmpty()) {
121
+ update toUpdate; // 1 DML regardless of list size
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### Partial Success DML
127
+
128
+ ```apex
129
+ List<Database.SaveResult> results = Database.insert(accounts, false);
130
+ List<String> errors = new List<String>();
131
+ for (Integer i = 0; i < results.size(); i++) {
132
+ if (!results[i].isSuccess()) {
133
+ for (Database.Error err : results[i].getErrors()) {
134
+ errors.add(accounts[i].Name + ': ' + err.getMessage());
135
+ }
136
+ }
137
+ }
138
+ if (!errors.isEmpty()) ErrorLogger.log(errors);
139
+ ```
140
+
141
+ ### Unit of Work Pattern
142
+
143
+ For complex transactions creating related records across multiple objects, collect all records and commit once to minimize DML statements.
144
+
145
+ ```apex
146
+ SimpleUnitOfWork uow = new SimpleUnitOfWork();
147
+ Account acc = new Account(Name = 'New Customer');
148
+ uow.registerNew(acc);
149
+ Contact primary = new Contact(LastName = 'Primary');
150
+ uow.registerNew(primary, Contact.AccountId, acc);
151
+ uow.commitWork(); // Minimal DML: inserts parent first, resolves IDs, then children
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Heap Limit Strategies
157
+
158
+ ### Select Minimal Fields
159
+
160
+ ```apex
161
+ // Use aggregate for count — do not load full sObjects just to count
162
+ Integer count = [SELECT COUNT() FROM Account];
163
+
164
+ // Select only fields the calling code needs
165
+ List<Account> accounts = [SELECT Id, Name FROM Account WHERE Id IN :accountIds];
166
+ ```
167
+
168
+ ### Use Maps Instead of Parallel Lists
169
+
170
+ ```apex
171
+ // Single data structure instead of two synchronized lists
172
+ Map<Id, String> accountNameById = new Map<Id, String>();
173
+ for (Account acc : accounts) {
174
+ accountNameById.put(acc.Id, acc.Name);
175
+ }
176
+ ```
177
+
178
+ ### Nullify Large References When Done
179
+
180
+ ```apex
181
+ List<SObject> largeDataSet = loadLargeDataSet();
182
+ List<String> results = extractResults(largeDataSet);
183
+ largeDataSet = null; // Eligible for garbage collection
184
+ saveResults(results);
185
+ ```
186
+
187
+ ---
188
+
189
+ ## CPU Time Strategies
190
+
191
+ ### Use Maps Instead of Nested Loops
192
+
193
+ ```apex
194
+ // O(n) using Set lookup instead of O(n^2) nested loop
195
+ Set<Id> validAccountIds = new Set<Id>(new Map<Id, Account>(validAccounts).keySet());
196
+ List<Contact> orphaned = new List<Contact>();
197
+ for (Contact con : contacts) {
198
+ if (!validAccountIds.contains(con.AccountId)) {
199
+ orphaned.add(con);
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Use String.join Instead of Concatenation in Loops
205
+
206
+ ```apex
207
+ List<String> names = new List<String>();
208
+ for (Account acc : accounts) names.add(acc.Name);
209
+ String output = String.join(names, ', '); // One allocation
210
+ ```
211
+
212
+ ### Offload to Async When CPU Is High
213
+
214
+ ```apex
215
+ if (Limits.getCpuTime() > 8000) { // 8 of 10 seconds used
216
+ System.enqueueJob(new AccountProcessorJob(
217
+ new List<Id>(new Map<Id, Account>(accounts).keySet())
218
+ ));
219
+ return;
220
+ }
221
+ performExpensiveProcessing(accounts);
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Callout Limit Strategies
227
+
228
+ ### @future(callout=true) from Triggers
229
+
230
+ Triggers cannot make synchronous callouts. Use @future to defer.
231
+
232
+ ```apex
233
+ public class AccountERPSyncService {
234
+ @future(callout=true)
235
+ public static void syncToERP(List<Id> accountIds) {
236
+ List<Account> accounts = [
237
+ SELECT Id, Name, External_Id__c FROM Account WHERE Id IN :accountIds
238
+ ];
239
+ for (Account acc : accounts) ERPClient.syncAccount(acc);
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### Queueable for Callout Chains
245
+
246
+ ```apex
247
+ public class SequentialCalloutJob implements Queueable, Database.AllowsCallouts {
248
+ private final List<Id> accountIds;
249
+ private final Integer currentIndex;
250
+
251
+ public SequentialCalloutJob(List<Id> accountIds) { this(accountIds, 0); }
252
+ private SequentialCalloutJob(List<Id> accountIds, Integer startIndex) {
253
+ this.accountIds = accountIds;
254
+ this.currentIndex = startIndex;
255
+ }
256
+
257
+ public void execute(QueueableContext ctx) {
258
+ final Integer CALLOUTS_PER_JOB = 90;
259
+ Integer end = Math.min(currentIndex + CALLOUTS_PER_JOB, accountIds.size());
260
+ for (Integer i = currentIndex; i < end; i++) {
261
+ ERPClient.syncAccount(accountIds[i]);
262
+ }
263
+ if (end < accountIds.size()) {
264
+ System.enqueueJob(new SequentialCalloutJob(accountIds, end));
265
+ }
266
+ }
267
+ }
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Async Decision Tree
273
+
274
+ ```
275
+ User action that can complete in < 5s? → Synchronous
276
+ Processing > 200 records? → Batch Apex
277
+ Callouts from a trigger? → @future(callout=true) or Queueable
278
+ CPU exceeding 8000ms regularly? → Profile first; then Queueable
279
+ Recurring scheduled operation? → Schedulable wrapping Batch/Queueable
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Testing at Limits
285
+
286
+ ```apex
287
+ @isTest
288
+ static void testTrigger_200RecordBulkInsert_noLimitException() {
289
+ List<Account> accounts = new List<Account>();
290
+ for (Integer i = 0; i < 200; i++) {
291
+ accounts.add(new Account(Name = 'Bulk Test ' + i, Type = 'Customer'));
292
+ }
293
+
294
+ Test.startTest(); // Resets governor limit counters
295
+ insert accounts;
296
+ Test.stopTest();
297
+
298
+ System.assertEquals(200,
299
+ [SELECT COUNT() FROM Account WHERE Type = 'Customer'],
300
+ 'All 200 accounts should be inserted');
301
+ }
302
+
303
+ @isTest
304
+ static void testService_queriesStayWithinLimits() {
305
+ List<Account> accounts = TestDataFactory.createAccounts(50);
306
+
307
+ Test.startTest();
308
+ Integer queriesBefore = Limits.getQueries();
309
+ AccountService.processAll(new Map<Id, Account>(accounts).keySet());
310
+ Integer queriesUsed = Limits.getQueries() - queriesBefore;
311
+ Test.stopTest();
312
+
313
+ System.assert(queriesUsed <= 5,
314
+ 'processAll() should use at most 5 SOQL queries. Actual: ' + queriesUsed);
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Related
321
+
322
+ - **Agent**: `sf-apex-agent` — For interactive, in-depth guidance
323
+ - **Constraints**: `sf-apex-constraints` — Hard rules for Apex governor compliance