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,326 @@
1
+ ---
2
+ name: sf-apex-async-patterns
3
+ description: "Async Apex patterns — @future, Queueable, Batch, Schedulable, Platform Events, chaining. Use when choosing or implementing async processing. Do NOT use for synchronous Apex or constraint enforcement."
4
+ origin: SCC
5
+ user-invocable: false
6
+ allowed-tools: Read, Grep, Glob, Edit, Write, Bash
7
+ ---
8
+
9
+ # Apex Async Patterns
10
+
11
+ Implementation guidance for asynchronous Apex. Covers when to use each pattern and how to implement it correctly. Governor limit numbers and hard rules live in the referenced files and `sf-apex-constraints`.
12
+
13
+ Reference: @../_reference/ASYNC_PATTERNS.md
14
+
15
+ ---
16
+
17
+ ## When to Use
18
+
19
+ - When synchronous Apex hits governor limits and needs a separate transaction
20
+ - When making HTTP callouts from trigger contexts
21
+ - When processing millions of records that exceed single-transaction limits
22
+ - When scheduling recurring Apex jobs on a cron-like schedule
23
+ - When decoupling event publishers from subscribers using Platform Events
24
+ - When deciding between `@future`, Queueable, Batch, Schedulable, or Platform Events
25
+
26
+ ---
27
+
28
+ ## Choosing the Right Pattern
29
+
30
+ | Requirement | Pattern |
31
+ |---|---|
32
+ | Simple async with no sObject params | `@future` |
33
+ | Need to pass sObjects or collections | `Queueable` |
34
+ | Need callouts from trigger context | `@future(callout=true)` |
35
+ | Need callouts with complex state | `Queueable + Database.AllowsCallouts` |
36
+ | Processing millions of records | `Batch Apex` |
37
+ | Need state across batches | `Batch Apex + Database.Stateful` |
38
+ | Run on a schedule | `Schedulable` (wraps Batch or Queueable) |
39
+ | Decouple publisher from subscriber | `Platform Events` |
40
+ | Chain jobs with delay | `Queueable + AsyncOptions` |
41
+
42
+ ---
43
+
44
+ ## @future Methods
45
+
46
+ The simplest async mechanism. Runs in a separate transaction with its own governor limits.
47
+
48
+ ```apex
49
+ public class ExternalDataSync {
50
+
51
+ @future(callout=true)
52
+ public static void syncAccountToERP(Id accountId) {
53
+ Account acc = [
54
+ SELECT Id, Name, BillingCity, AnnualRevenue
55
+ FROM Account WHERE Id = :accountId LIMIT 1
56
+ ];
57
+
58
+ HttpRequest req = new HttpRequest();
59
+ req.setEndpoint('callout:ERP_System/accounts');
60
+ req.setMethod('POST');
61
+ req.setHeader('Content-Type', 'application/json');
62
+ req.setBody(JSON.serialize(new ERPAccountPayload(acc)));
63
+
64
+ HttpResponse res = new Http().send(req);
65
+ if (res.getStatusCode() != 200) {
66
+ logSyncError(accountId, res.getStatusCode(), res.getBody());
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### @future Constraints
73
+
74
+ - **No sObject parameters** — pass primitive types (Id, String) or serialized JSON. sObjects may change between enqueue and execution.
75
+ - **No chaining** — calling `@future` from another `@future` throws a runtime exception.
76
+ - **50 per transaction** — governor limit on future method invocations.
77
+ - **No return value** — fire-and-forget only.
78
+ - **Execution order not guaranteed**.
79
+
80
+ ---
81
+
82
+ ## Queueable Apex
83
+
84
+ More powerful than `@future`. Supports sObject parameters, chaining, and monitoring via `AsyncApexJob`.
85
+
86
+ ### Basic Queueable
87
+
88
+ ```apex
89
+ public class AccountEnrichmentJob implements Queueable {
90
+
91
+ private final List<Account> accounts;
92
+
93
+ public AccountEnrichmentJob(List<Account> accounts) {
94
+ this.accounts = accounts;
95
+ }
96
+
97
+ public void execute(QueueableContext context) {
98
+ List<Account> toUpdate = new List<Account>();
99
+ for (Account acc : accounts) {
100
+ if (acc.AnnualRevenue != null && acc.NumberOfEmployees != null
101
+ && acc.NumberOfEmployees > 0) {
102
+ toUpdate.add(new Account(
103
+ Id = acc.Id,
104
+ Revenue_Per_Employee__c = acc.AnnualRevenue / acc.NumberOfEmployees
105
+ ));
106
+ }
107
+ }
108
+ if (!toUpdate.isEmpty()) update toUpdate;
109
+ }
110
+ }
111
+
112
+ // Enqueue
113
+ System.enqueueJob(new AccountEnrichmentJob(accounts));
114
+ ```
115
+
116
+ ### Queueable with Callouts
117
+
118
+ Implement `Database.AllowsCallouts` alongside `Queueable`.
119
+
120
+ ```apex
121
+ public class ContactDataEnrichmentJob implements Queueable, Database.AllowsCallouts {
122
+ private final Set<Id> contactIds;
123
+
124
+ public ContactDataEnrichmentJob(Set<Id> contactIds) {
125
+ this.contactIds = contactIds;
126
+ }
127
+
128
+ public void execute(QueueableContext context) {
129
+ // Query, callout, update pattern
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### Chaining Queueable Jobs
135
+
136
+ Use chaining to process large data sets across multiple transactions. Use WHERE clauses to naturally shrink the result set instead of OFFSET (which has a 2,000-row hard limit).
137
+
138
+ ```apex
139
+ public class DataMigrationChainJob implements Queueable {
140
+
141
+ private static final Integer BATCH_SIZE = 200;
142
+
143
+ public void execute(QueueableContext context) {
144
+ List<Legacy_Record__c> batch = [
145
+ SELECT Id, Legacy_Field__c
146
+ FROM Legacy_Record__c
147
+ WHERE Migrated__c = false
148
+ ORDER BY CreatedDate
149
+ LIMIT :BATCH_SIZE
150
+ ];
151
+
152
+ if (batch.isEmpty()) return; // Migration complete
153
+
154
+ processBatch(batch);
155
+
156
+ // Chain next job — WHERE Migrated__c = false naturally shrinks each iteration
157
+ System.enqueueJob(new DataMigrationChainJob());
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### AsyncOptions
163
+
164
+ ```apex
165
+ // Delay execution by 5 minutes
166
+ System.AsyncOptions opts = new System.AsyncOptions();
167
+ opts.minimumQueueableDelayInMinutes = 5;
168
+ System.enqueueJob(new MyQueueableJob(data), opts);
169
+
170
+ // Duplicate prevention with a unique key
171
+ System.AsyncOptions opts2 = new System.AsyncOptions();
172
+ opts2.duplicateSignature = 'account-sync-' + accountId;
173
+ System.enqueueJob(new AccountSyncJob(accountId), opts2);
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Batch Apex
179
+
180
+ For processing large data volumes (millions of records) that exceed single-transaction limits.
181
+
182
+ ### Basic Batch
183
+
184
+ ```apex
185
+ public class AccountAnnualReviewBatch
186
+ implements Database.Batchable<SObject>, Database.Stateful {
187
+
188
+ private Integer processedCount = 0;
189
+ private List<String> errors = new List<String>();
190
+
191
+ public Database.QueryLocator start(Database.BatchableContext bc) {
192
+ return Database.getQueryLocator([
193
+ SELECT Id, Name, AnnualRevenue, Last_Annual_Review__c, OwnerId
194
+ FROM Account
195
+ WHERE Type = 'Customer'
196
+ AND (Last_Annual_Review__c = null
197
+ OR Last_Annual_Review__c < LAST_N_DAYS:365)
198
+ ]);
199
+ }
200
+
201
+ public void execute(Database.BatchableContext bc, List<Account> scope) {
202
+ // Process scope — each execute() is its own transaction
203
+ // Default scope = 200 records
204
+ }
205
+
206
+ public void finish(Database.BatchableContext bc) {
207
+ // Cleanup and notifications
208
+ }
209
+ }
210
+
211
+ // Execute (default scope of 200)
212
+ Database.executeBatch(new AccountAnnualReviewBatch());
213
+
214
+ // Custom scope (smaller for complex processing or callouts)
215
+ Database.executeBatch(new AccountAnnualReviewBatch(), 50);
216
+ ```
217
+
218
+ ### Batch with Callouts
219
+
220
+ Implement `Database.AllowsCallouts` and set scope = 1 when each callout is per-record (each execute() is limited to 100 callouts).
221
+
222
+ ```apex
223
+ public class SingleRecordCalloutBatch
224
+ implements Database.Batchable<SObject>, Database.AllowsCallouts {
225
+ // scope = 1 in executeBatch call
226
+ }
227
+ Database.executeBatch(new SingleRecordCalloutBatch(), 1);
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Schedulable Apex
233
+
234
+ Runs Apex on a schedule. Best practice: schedulable should only coordinate, not do heavy work.
235
+
236
+ ```apex
237
+ public class WeeklyReportScheduler implements Schedulable {
238
+ public void execute(SchedulableContext sc) {
239
+ Database.executeBatch(new WeeklyReportBatch(), 200);
240
+ }
241
+ }
242
+
243
+ // Schedule
244
+ String cronExp = '0 0 6 ? * MON'; // Every Monday at 6:00 AM
245
+ System.schedule('Weekly Report - Monday 6AM', cronExp, new WeeklyReportScheduler());
246
+ ```
247
+
248
+ ### Cron Expression Reference
249
+
250
+ ```
251
+ 0 0 2 * * ? — Daily at 2:00 AM
252
+ 0 0 9 ? * MON-FRI — Weekdays at 9:00 AM
253
+ 0 0 0 1 * ? * — First day of every month at midnight
254
+ 0 30 8 ? * SAT — Every Saturday at 8:30 AM
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Platform Events
260
+
261
+ Decouple publishers from subscribers. Subscribers run in their own transaction.
262
+
263
+ ### Publishing
264
+
265
+ ```apex
266
+ List<Order_Status_Change__e> events = new List<Order_Status_Change__e>();
267
+ for (Order__c order : orders) {
268
+ events.add(new Order_Status_Change__e(
269
+ Order_Id__c = order.Id,
270
+ New_Status__c = newStatus,
271
+ Changed_By__c = UserInfo.getUserId(),
272
+ Timestamp__c = Datetime.now()
273
+ ));
274
+ }
275
+ List<Database.SaveResult> results = EventBus.publish(events);
276
+ ```
277
+
278
+ > By default, high-volume platform events use "publish after commit" behavior. To publish immediately regardless of transaction outcome, configure the event's Publish Behavior to "Publish Immediately" in Setup.
279
+
280
+ ### Subscribing via Trigger
281
+
282
+ ```apex
283
+ trigger OrderStatusChangeTrigger on Order_Status_Change__e (after insert) {
284
+ for (Order_Status_Change__e event : Trigger.new) {
285
+ // Process event — runs in its own transaction
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### High-Volume Events and ReplayId
291
+
292
+ ```apex
293
+ trigger HighVolumeEventTrigger on Analytics_Event__e (after insert) {
294
+ // Set resume checkpoint for retry-after-failure
295
+ EventBus.TriggerContext.currentContext().setResumeCheckpoint(
296
+ Trigger.new[Trigger.new.size() - 1].ReplayId
297
+ );
298
+ }
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Testing Async Apex
304
+
305
+ `Test.startTest()` / `Test.stopTest()` forces @future, Queueable, and Batch jobs to execute synchronously. Platform events are also delivered synchronously within the test boundary.
306
+
307
+ ```apex
308
+ @isTest
309
+ static void testBatchUpdatesReviewDate() {
310
+ // Insert test data
311
+ Test.startTest();
312
+ Database.executeBatch(new AccountAnnualReviewBatch(), 200);
313
+ Test.stopTest(); // All batch methods run synchronously
314
+ // Assert results
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Related
321
+
322
+ - **Agents**: `sf-review-agent`, `sf-apex-agent` — For interactive guidance
323
+
324
+ ### Guardrails
325
+
326
+ - `sf-apex-constraints` — Governs limits, bulkification rules, and naming conventions for all Apex code including async