@salesforce/afv-skills 1.28.0 → 1.30.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 (235) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/skills/agentforce-architecture-analyze/README.md +2 -8
  4. package/skills/agentforce-architecture-analyze/SKILL.md +2 -2
  5. package/skills/agentforce-architecture-analyze/references/contract.json +4 -4
  6. package/skills/agentforce-architecture-analyze/references/soql_fields.md +1 -1
  7. package/skills/data360-activate/README.md +0 -1
  8. package/skills/data360-activate/SKILL.md +0 -2
  9. package/skills/data360-connect/README.md +0 -2
  10. package/skills/data360-connect/SKILL.md +0 -2
  11. package/skills/data360-harmonize/SKILL.md +0 -1
  12. package/skills/data360-orchestrate/README.md +0 -7
  13. package/skills/data360-orchestrate/SKILL.md +0 -2
  14. package/skills/data360-prepare/README.md +0 -1
  15. package/skills/data360-prepare/SKILL.md +0 -1
  16. package/skills/data360-query/README.md +0 -1
  17. package/skills/data360-query/SKILL.md +0 -1
  18. package/skills/data360-segment/README.md +0 -1
  19. package/skills/data360-segment/SKILL.md +0 -2
  20. package/skills/dx-code-analyzer-configure/SKILL.md +31 -13
  21. package/skills/dx-code-analyzer-custom-rule-create/SKILL.md +484 -0
  22. package/skills/dx-code-analyzer-custom-rule-create/assets/pmd-ruleset-template.xml +31 -0
  23. package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-fields-api.md +87 -0
  24. package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-flows.md +105 -0
  25. package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-permissions.md +95 -0
  26. package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-examples.md +84 -0
  27. package/skills/dx-code-analyzer-custom-rule-create/examples/regex-examples.md +127 -0
  28. package/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md +227 -0
  29. package/skills/dx-code-analyzer-custom-rule-create/references/advanced-pmd-patterns.md +288 -0
  30. package/skills/dx-code-analyzer-custom-rule-create/references/apex-ast-reference.md +127 -0
  31. package/skills/dx-code-analyzer-custom-rule-create/references/eslint-custom-plugins.md +247 -0
  32. package/skills/dx-code-analyzer-custom-rule-create/references/eslint-rules-discovery.md +188 -0
  33. package/skills/dx-code-analyzer-custom-rule-create/references/eslint-tier2-configurable.md +114 -0
  34. package/skills/dx-code-analyzer-custom-rule-create/references/eslint-tier3-custom-plugins.md +113 -0
  35. package/skills/dx-code-analyzer-custom-rule-create/references/metadata-xml-rules.md +285 -0
  36. package/skills/dx-code-analyzer-custom-rule-create/references/regex-rule-schema.md +174 -0
  37. package/skills/dx-code-analyzer-custom-rule-create/references/troubleshooting.md +141 -0
  38. package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-governor-limits.md +83 -0
  39. package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-method-calls.md +108 -0
  40. package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md +45 -0
  41. package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-structure.md +127 -0
  42. package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns.md +131 -0
  43. package/skills/dx-code-analyzer-custom-rule-create/scripts/create-pmd-rule.js +209 -0
  44. package/skills/dx-code-analyzer-custom-rule-create/scripts/create-regex-rule.js +220 -0
  45. package/skills/dx-code-analyzer-run/SKILL.md +41 -8
  46. package/skills/experience-cms-brand-apply/SKILL.md +47 -16
  47. package/skills/experience-lwc-generate/README.md +3 -2
  48. package/skills/experience-lwc-generate/references/async-notification-patterns.md +1 -1
  49. package/skills/experience-lwc-generate/references/component-patterns.md +3 -3
  50. package/skills/experience-lwc-generate/references/flow-integration-guide.md +1 -1
  51. package/skills/experience-lwc-generate/references/lwc-best-practices.md +4 -4
  52. package/skills/experience-lwc-generate/references/scoring-and-testing.md +1 -1
  53. package/skills/experience-lwc-generate/references/state-management.md +2 -2
  54. package/skills/experience-lwc-generate/references/triangle-pattern.md +3 -3
  55. package/skills/experience-lwc-generate/scripts/post-tool-validate.py +2 -2
  56. package/skills/experience-lwc-generate/scripts/template_validator.py +1 -1
  57. package/skills/external-diagram-mermaid-generate/README.md +2 -2
  58. package/skills/external-diagram-mermaid-generate/SKILL.md +1 -3
  59. package/skills/external-diagram-mermaid-generate/assets/agentforce/agent-flow.md +4 -4
  60. package/skills/external-diagram-mermaid-generate/assets/architecture/system-landscape.md +1 -1
  61. package/skills/external-diagram-mermaid-generate/assets/datamodel/b2b-commerce-erd.md +3 -3
  62. package/skills/external-diagram-mermaid-generate/assets/datamodel/campaigns-erd.md +1 -1
  63. package/skills/external-diagram-mermaid-generate/assets/datamodel/consent-erd.md +2 -2
  64. package/skills/external-diagram-mermaid-generate/assets/datamodel/files-erd.md +2 -2
  65. package/skills/external-diagram-mermaid-generate/assets/datamodel/forecasting-erd.md +2 -2
  66. package/skills/external-diagram-mermaid-generate/assets/datamodel/fsl-erd.md +2 -2
  67. package/skills/external-diagram-mermaid-generate/assets/datamodel/party-model-erd.md +1 -1
  68. package/skills/external-diagram-mermaid-generate/assets/datamodel/quote-order-erd.md +3 -3
  69. package/skills/external-diagram-mermaid-generate/assets/datamodel/revenue-cloud-erd.md +2 -2
  70. package/skills/external-diagram-mermaid-generate/assets/datamodel/sales-cloud-erd.md +1 -1
  71. package/skills/external-diagram-mermaid-generate/assets/datamodel/salesforce-erd.md +1 -1
  72. package/skills/external-diagram-mermaid-generate/assets/datamodel/scheduler-erd.md +2 -2
  73. package/skills/external-diagram-mermaid-generate/assets/datamodel/service-cloud-erd.md +3 -3
  74. package/skills/external-diagram-mermaid-generate/assets/datamodel/territory-management-erd.md +1 -1
  75. package/skills/external-diagram-mermaid-generate/assets/integration/api-sequence.md +1 -1
  76. package/skills/external-diagram-mermaid-generate/assets/oauth/authorization-code-pkce.md +1 -1
  77. package/skills/external-diagram-mermaid-generate/assets/oauth/authorization-code.md +1 -1
  78. package/skills/external-diagram-mermaid-generate/assets/oauth/client-credentials.md +1 -1
  79. package/skills/external-diagram-mermaid-generate/assets/oauth/device-authorization.md +2 -2
  80. package/skills/external-diagram-mermaid-generate/assets/oauth/jwt-bearer.md +2 -2
  81. package/skills/external-diagram-mermaid-generate/assets/oauth/refresh-token.md +1 -1
  82. package/skills/external-diagram-mermaid-generate/assets/oauth/user-agent-social-sign-on.md +2 -2
  83. package/skills/external-diagram-mermaid-generate/assets/role-hierarchy/user-hierarchy.md +1 -1
  84. package/skills/external-diagram-mermaid-generate/references/color-palette.md +13 -13
  85. package/skills/external-diagram-mermaid-generate/references/diagram-conventions.md +5 -5
  86. package/skills/external-diagram-mermaid-generate/references/erd-conventions.md +1 -1
  87. package/skills/external-diagram-mermaid-generate/references/mermaid-styling.md +2 -2
  88. package/skills/external-diagram-mermaid-generate/references/preview-guide.md +1 -1
  89. package/skills/external-diagram-mermaid-generate/references/usage-examples.md +9 -9
  90. package/skills/external-diagram-mermaid-generate/scripts/README.md +1 -1
  91. package/skills/integration-connectivity-connected-app-configure/README.md +4 -5
  92. package/skills/integration-connectivity-connected-app-configure/SKILL.md +2 -2
  93. package/skills/integration-connectivity-connected-app-configure/references/example-usage.md +7 -7
  94. package/skills/integration-connectivity-connected-app-configure/references/migration-guide.md +1 -1
  95. package/skills/integration-connectivity-connected-app-configure/references/oauth-flows-reference.md +1 -1
  96. package/skills/integration-connectivity-connected-app-configure/references/testing-validation-guide.md +3 -3
  97. package/skills/integration-connectivity-generate/README.md +1 -1
  98. package/skills/integration-connectivity-generate/SKILL.md +6 -0
  99. package/skills/integration-connectivity-generate/assets/callouts/rest-queueable-callout.cls +1 -1
  100. package/skills/integration-connectivity-generate/assets/external-services/external-service-operations.md +1 -1
  101. package/skills/integration-connectivity-generate/assets/soap/wsdl2apex-guide.md +1 -1
  102. package/skills/integration-connectivity-generate/references/callout-patterns.md +4 -0
  103. package/skills/integration-connectivity-generate/references/cdc-guide.md +2 -2
  104. package/skills/integration-connectivity-generate/references/event-driven-architecture-guide.md +5 -5
  105. package/skills/integration-connectivity-generate/references/event-patterns.md +3 -2
  106. package/skills/integration-connectivity-generate/references/external-services-guide.md +4 -1
  107. package/skills/integration-connectivity-generate/references/messaging-api-v2.md +2 -2
  108. package/skills/integration-connectivity-generate/references/named-credentials-automation.md +1 -1
  109. package/skills/integration-connectivity-generate/references/named-credentials-guide.md +12 -2
  110. package/skills/integration-connectivity-generate/references/platform-events-guide.md +3 -3
  111. package/skills/integration-connectivity-generate/references/rest-callout-patterns.md +1 -1
  112. package/skills/integration-connectivity-generate/references/scoring-rubric.md +1 -1
  113. package/skills/integration-connectivity-generate/references/security-best-practices.md +5 -2
  114. package/skills/integration-connectivity-generate/scripts/configure-named-credential.sh +16 -5
  115. package/skills/integration-connectivity-generate/scripts/set-api-credential.sh +11 -2
  116. package/skills/integration-connectivity-generate/scripts/suggest_credential_setup.py +4 -3
  117. package/skills/integration-connectivity-generate/scripts/validate_integration.py +1 -1
  118. package/skills/mobile-platform-native-capabilities-integrate/SKILL.md +3 -3
  119. package/skills/omnistudio-callable-apex-generate/README.md +1 -5
  120. package/skills/omnistudio-callable-apex-generate/SKILL.md +14 -4
  121. package/skills/omnistudio-callable-apex-generate/assets/pattern_callable_vanilla.cls +8 -1
  122. package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md +1 -1
  123. package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md +1 -1
  124. package/skills/omnistudio-datamapper-generate/SKILL.md +1 -1
  125. package/skills/omnistudio-datamapper-generate/assets/completion-summary-template.md +2 -2
  126. package/skills/omnistudio-datamapper-generate/references/best-practices.md +9 -9
  127. package/skills/omnistudio-datamapper-generate/references/naming-conventions.md +6 -6
  128. package/skills/omnistudio-datapacks-deploy/README.md +1 -1
  129. package/skills/omnistudio-datapacks-deploy/examples/business-internet-plus-bundle/deploy-business-internet-plus-bundle.yaml +1 -1
  130. package/skills/omnistudio-dependencies-analyze/SKILL.md +12 -5
  131. package/skills/omnistudio-dependencies-analyze/references/dependency-patterns.md +9 -9
  132. package/skills/omnistudio-dependencies-analyze/references/namespace-guide.md +1 -1
  133. package/skills/omnistudio-epc-catalog-generate/README.md +1 -1
  134. package/skills/omnistudio-flexcard-generate/SKILL.md +11 -4
  135. package/skills/omnistudio-flexcard-generate/references/best-practices.md +6 -6
  136. package/skills/omnistudio-flexcard-generate/references/data-binding-guide.md +9 -9
  137. package/skills/omnistudio-integration-procedure-generate/SKILL.md +9 -1
  138. package/skills/omnistudio-integration-procedure-generate/references/element-types.md +3 -3
  139. package/skills/omnistudio-omniscript-generate/SKILL.md +2 -2
  140. package/skills/omnistudio-omniscript-generate/references/best-practices.md +1 -1
  141. package/skills/omnistudio-omniscript-generate/scripts/check-duplicate-omniscript.sh +8 -0
  142. package/skills/omnistudio-omniscript-generate/scripts/deploy-omniscript.sh +8 -0
  143. package/skills/platform-apex-logs-debug/README.md +2 -2
  144. package/skills/platform-apex-logs-debug/references/cli-commands.md +2 -2
  145. package/skills/platform-apex-logs-debug/references/debug-log-reference.md +16 -16
  146. package/skills/platform-apex-logs-debug/references/log-analysis-tools.md +2 -2
  147. package/skills/platform-apex-test-run/README.md +1 -1
  148. package/skills/platform-apex-test-run/references/test-fix-loop.md +2 -2
  149. package/skills/platform-apex-test-run/references/testing-best-practices.md +3 -3
  150. package/skills/platform-custom-field-generate/SKILL.md +86 -126
  151. package/skills/platform-custom-field-generate/references/advanced-picklists.md +590 -0
  152. package/skills/platform-data-manage/README.md +4 -4
  153. package/skills/platform-data-manage/references/bulk-testing-example.md +1 -1
  154. package/skills/platform-data-manage/references/crud-workflow-example.md +2 -2
  155. package/skills/platform-data-manage/references/orchestration.md +6 -6
  156. package/skills/platform-flexipage-generate/SKILL.md +281 -346
  157. package/skills/platform-flexipage-generate/references/cli_commands.md +39 -0
  158. package/skills/platform-flexipage-generate/references/flexipage_fieldSection.md +162 -0
  159. package/skills/platform-flexipage-generate/references/flexipage_richText.md +84 -0
  160. package/skills/platform-flexipage-generate/references/identifiers_and_regions.md +167 -0
  161. package/skills/platform-flexipage-generate/references/mcp_action_examples.md +104 -0
  162. package/skills/platform-flexipage-generate/references/record_flexipage_dynamicHighlights.md +119 -0
  163. package/skills/platform-flexipage-generate/references/xml_rules.md +335 -0
  164. package/skills/platform-flexipage-generate/scripts/resolve-component-instructions.sh +42 -0
  165. package/skills/platform-flexipage-generate/scripts/scan-lwc-components.sh +113 -0
  166. package/skills/platform-metadata-deploy/README.md +2 -2
  167. package/skills/platform-metadata-deploy/references/agent-deployment-guide.md +2 -2
  168. package/skills/platform-metadata-deploy/references/deployment-workflows.md +16 -16
  169. package/skills/platform-metadata-deploy/references/orchestration.md +3 -3
  170. package/skills/platform-metadata-deploy/references/trigger-deployment-safety.md +2 -2
  171. package/skills/platform-models-api-configure/SKILL.md +140 -0
  172. package/skills/platform-models-api-configure/scripts/get-orgjwt.sh +48 -0
  173. package/skills/platform-policy-rule-generate/SKILL.md +260 -0
  174. package/skills/platform-policy-rule-generate/references/deploy-errors.md +54 -0
  175. package/skills/platform-policy-rule-generate/references/fixtures-index.md +29 -0
  176. package/skills/platform-policy-rule-generate/references/policy-schema-full.md +250 -0
  177. package/skills/platform-policy-rule-generate/references/templates-access.md +132 -0
  178. package/skills/platform-policy-rule-generate/references/templates-advanced.md +58 -0
  179. package/skills/platform-policy-rule-generate/references/templates-record.md +75 -0
  180. package/skills/platform-policy-rule-generate/references/templates-transform.md +70 -0
  181. package/skills/platform-policy-rule-generate/references/templates.md +10 -0
  182. package/skills/platform-policy-rule-generate/references/ui-compatibility.md +142 -0
  183. package/skills/platform-soql-query/README.md +1 -1
  184. package/skills/platform-soql-query/SKILL.md +1 -1
  185. package/skills/platform-soql-query/references/anti-patterns.md +1 -1
  186. package/skills/platform-soql-query/references/field-coverage-rules.md +1 -1
  187. package/skills/platform-soql-query/references/query-optimization.md +1 -1
  188. package/skills/platform-soql-query/scripts/post-tool-validate.py +3 -3
  189. package/skills/platform-value-set-generate/SKILL.md +305 -0
  190. package/skills/data360-activate/CREDITS.md +0 -5
  191. package/skills/data360-connect/CREDITS.md +0 -5
  192. package/skills/data360-harmonize/CREDITS.md +0 -3
  193. package/skills/data360-orchestrate/CREDITS.md +0 -15
  194. package/skills/data360-orchestrate/UPSTREAM.md +0 -45
  195. package/skills/data360-prepare/CREDITS.md +0 -7
  196. package/skills/data360-query/CREDITS.md +0 -7
  197. package/skills/data360-segment/CREDITS.md +0 -3
  198. package/skills/experience-lwc-generate/CREDITS.md +0 -5
  199. package/skills/external-diagram-mermaid-generate/CREDITS.md +0 -46
  200. package/skills/external-diagram-visual-generate/CREDITS.md +0 -80
  201. package/skills/external-diagram-visual-generate/README.md +0 -83
  202. package/skills/external-diagram-visual-generate/SKILL.md +0 -207
  203. package/skills/external-diagram-visual-generate/assets/architecture/integration-flow.md +0 -55
  204. package/skills/external-diagram-visual-generate/assets/erd/core-objects.md +0 -131
  205. package/skills/external-diagram-visual-generate/assets/erd/custom-objects.md +0 -60
  206. package/skills/external-diagram-visual-generate/assets/lwc/dashboard-card.md +0 -45
  207. package/skills/external-diagram-visual-generate/assets/lwc/data-table.md +0 -57
  208. package/skills/external-diagram-visual-generate/assets/lwc/record-form.md +0 -60
  209. package/skills/external-diagram-visual-generate/assets/review/apex-review.md +0 -57
  210. package/skills/external-diagram-visual-generate/assets/review/lwc-review.md +0 -48
  211. package/skills/external-diagram-visual-generate/references/architect-aesthetic-guide.md +0 -257
  212. package/skills/external-diagram-visual-generate/references/examples-index.md +0 -35
  213. package/skills/external-diagram-visual-generate/references/gemini-cli-setup.md +0 -65
  214. package/skills/external-diagram-visual-generate/references/interview-questions.md +0 -529
  215. package/skills/external-diagram-visual-generate/references/iteration-workflow.md +0 -173
  216. package/skills/external-diagram-visual-generate/scripts/check-prerequisites.sh +0 -101
  217. package/skills/external-diagram-visual-generate/scripts/generate_image.py +0 -243
  218. package/skills/integration-connectivity-connected-app-configure/CREDITS.md +0 -3
  219. package/skills/integration-connectivity-generate/CREDITS.md +0 -5
  220. package/skills/omnistudio-callable-apex-generate/CREDITS.md +0 -9
  221. package/skills/omnistudio-datamapper-generate/CREDITS.md +0 -5
  222. package/skills/omnistudio-datapacks-deploy/CREDITS.md +0 -5
  223. package/skills/omnistudio-dependencies-analyze/CREDITS.md +0 -5
  224. package/skills/omnistudio-epc-catalog-generate/CREDITS.md +0 -14
  225. package/skills/omnistudio-flexcard-generate/CREDITS.md +0 -5
  226. package/skills/omnistudio-integration-procedure-generate/CREDITS.md +0 -5
  227. package/skills/omnistudio-omniscript-generate/CREDITS.md +0 -5
  228. package/skills/platform-apex-generate/CREDITS.md +0 -5
  229. package/skills/platform-apex-logs-debug/CREDITS.md +0 -22
  230. package/skills/platform-apex-test-generate/CREDITS.md +0 -5
  231. package/skills/platform-apex-test-run/CREDITS.md +0 -22
  232. package/skills/platform-data-manage/CREDITS.md +0 -5
  233. package/skills/platform-metadata-deploy/CREDITS.md +0 -25
  234. package/skills/platform-soql-query/CREDITS.md +0 -21
  235. /package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterfaceConversion/{MyCustomVlocityOpenInterface2.cls → MyCustomClass.cls} +0 -0
@@ -0,0 +1,188 @@
1
+ # ESLint Rules Discovery & Configuration
2
+
3
+ **READ THIS FIRST** for ANY ESLint request. 90% of ESLint rules already exist — this guide shows you how to find and configure them instead of creating custom plugins.
4
+
5
+ ---
6
+
7
+ ## Three Tiers of ESLint Rules
8
+
9
+ | Tier | What It Is | When to Use | Effort | Coverage |
10
+ |---|---|---|---|---|
11
+ | **Tier 1: Built-In Rules** | 200+ core ESLint rules | First choice — check here FIRST | LOW (enable in config) | 70% of requests |
12
+ | **Tier 2: Configurable Rules** | no-restricted-syntax, no-restricted-globals, no-restricted-properties | When no built-in rule exists but pattern is generic | MEDIUM (AST selector) | 20% of requests |
13
+ | **Tier 3: Custom Plugins** | Write your own ESLint plugin | LAST RESORT — domain-specific multi-node patterns only | HIGH (Node code, testing) | 10% of requests |
14
+
15
+ **Always start at Tier 1 and work down.**
16
+
17
+ ---
18
+
19
+ ## Tier 1: Discover Built-In Rules
20
+
21
+ ### Discovery Workflow (MANDATORY)
22
+
23
+ Before creating ANY custom ESLint rule:
24
+
25
+ 1. **Run:** `sf code-analyzer rules --rule-selector eslint`
26
+ 2. **Search output** for keywords from the user's request:
27
+ - User says "ban console.log" → search for "console"
28
+ - User says "enforce ===" → search for "equal" or "strict"
29
+ - User says "no unused variables" → search for "unused"
30
+ 3. **Check naming patterns:**
31
+ - `no-*` — Disallow something (no-console, no-debugger, no-eval)
32
+ - `prefer-*` — Prefer one style (prefer-const, prefer-arrow-callback)
33
+ - `require-*` — Require something (require-await, require-yield)
34
+ - `@lwc/lwc/*` — LWC-specific rules (no-inner-html, no-document-query)
35
+ 4. **If found:** Configure it (see "Configuration Workflow" below). **STOP — do NOT create a custom plugin.**
36
+ 5. **If NOT found:** Proceed to Tier 2.
37
+
38
+ ### Common Built-In Rules by Category
39
+
40
+ #### Code Quality
41
+ | User Request | Rule Name | Config Example |
42
+ |---|---|---|
43
+ | "No unused variables" | `no-unused-vars` | `"no-unused-vars": "error"` |
44
+ | "No unused imports" | `no-unused-vars` | Same rule covers imports |
45
+ | "Require await in async functions" | `require-await` | `"require-await": "error"` |
46
+ | "No empty blocks" | `no-empty` | `"no-empty": "error"` |
47
+ | "No unreachable code" | `no-unreachable` | `"no-unreachable": "error"` |
48
+
49
+ #### Security
50
+ | User Request | Rule Name | Config Example |
51
+ |---|---|---|
52
+ | "Ban eval()" | `no-eval` | `"no-eval": "error"` |
53
+ | "Ban debugger" | `no-debugger` | `"no-debugger": "error"` |
54
+ | "No implied eval" | `no-implied-eval` | `"no-implied-eval": "error"` |
55
+ | "Ban alert()" | `no-alert` | `"no-alert": "error"` |
56
+
57
+ #### Best Practices
58
+ | User Request | Rule Name | Config Example |
59
+ |---|---|---|
60
+ | "Enforce ===" | `eqeqeq` | `"eqeqeq": ["error", "always"]` |
61
+ | "Prefer const" | `prefer-const` | `"prefer-const": "error"` |
62
+ | "No var" | `no-var` | `"no-var": "error"` |
63
+ | "Prefer arrow functions" | `prefer-arrow-callback` | `"prefer-arrow-callback": "error"` |
64
+ | "Require default in switch" | `default-case` | `"default-case": "error"` |
65
+
66
+ #### Logging/Debugging
67
+ | User Request | Rule Name | Config Example |
68
+ |---|---|---|
69
+ | "Ban console.log" | `no-console` | `"no-console": "error"` |
70
+ | "Ban console.* except error" | `no-console` | `"no-console": ["error", { "allow": ["error", "warn"] }]` |
71
+
72
+ ### LWC Plugin Rules (Check if Available)
73
+
74
+ If Code Analyzer has `@lwc/eslint-plugin-lwc` enabled:
75
+
76
+ | User Request | Rule Name | Notes |
77
+ |---|---|---|
78
+ | "Ban innerHTML" | `@lwc/lwc/no-inner-html` | XSS prevention |
79
+ | "No document.querySelector" | `@lwc/lwc/no-document-query` | Use template queries |
80
+ | "Validate @api usage" | `@lwc/lwc/no-api-reassignments` | Prevents reassigning @api properties |
81
+ | "Validate @wire syntax" | `@lwc/lwc/valid-wire` | Built-in |
82
+ | "No async in getters" | `@lwc/lwc/no-async-operation` | Lifecycle hook validation |
83
+
84
+ **Check availability:**
85
+ ```bash
86
+ sf code-analyzer rules --rule-selector eslint | grep -i "@lwc"
87
+ ```
88
+
89
+ ### External Documentation
90
+
91
+ - **All ESLint built-in rules:** https://eslint.org/docs/latest/rules/
92
+ - **LWC ESLint plugin:** https://github.com/salesforce/eslint-plugin-lwc
93
+ - **Salesforce Lightning plugin:** https://github.com/forcedotcom/eslint-plugin-lightning
94
+
95
+ ---
96
+
97
+ ## Configuration Workflow (Tier 1)
98
+
99
+ When a built-in rule exists:
100
+
101
+ 1. **Create `eslint.config.js`** if it doesn't exist:
102
+ ```javascript
103
+ module.exports = [
104
+ {
105
+ files: ["**/lwc/**/*.js"], // or ["**/*.js"] for all JS files
106
+ rules: {
107
+ // Rules go here
108
+ }
109
+ }
110
+ ];
111
+ ```
112
+
113
+ 2. **Add the rule** with desired severity:
114
+ ```javascript
115
+ rules: {
116
+ "no-console": "error", // Ban completely
117
+ "eqeqeq": ["error", "always"], // With options
118
+ "no-unused-vars": ["warn"] // Warning instead of error
119
+ }
120
+ ```
121
+
122
+ 3. **Update `code-analyzer.yml`** (AFTER file exists):
123
+ ```yaml
124
+ engines:
125
+ eslint:
126
+ eslint_config_file: "eslint.config.js"
127
+ ```
128
+
129
+ 4. **Validate:**
130
+ ```bash
131
+ sf code-analyzer rules --rule-selector eslint:no-console
132
+ ```
133
+ If the rule does NOT appear in the output, the config is wrong. Do NOT proceed to testing.
134
+
135
+ 5. **Test positive:**
136
+ ```bash
137
+ sf code-analyzer run --rule-selector eslint:no-console --target lwc/
138
+ ```
139
+
140
+ 6. **Test negative:** Run against clean code, confirm 0 violations.
141
+
142
+ ---
143
+
144
+ ## Tier 2 and Tier 3: Configurable Rules and Custom Plugins
145
+
146
+ For detailed information on these tiers:
147
+
148
+ | Tier | File | When to Use |
149
+ |------|------|-------------|
150
+ | **Tier 2: Configurable Rules** | [eslint-tier2-configurable.md](eslint-tier2-configurable.md) | no-restricted-globals, no-restricted-syntax, no-restricted-properties — ban specific patterns without writing plugins |
151
+ | **Tier 3: Custom Plugins** | [eslint-tier3-custom-plugins.md](eslint-tier3-custom-plugins.md) | Complete examples for all tiers + when to create custom plugins (LAST RESORT) |
152
+
153
+ ---
154
+
155
+ ## Decision Tree
156
+
157
+ ```text
158
+ User asks for ESLint rule
159
+
160
+ Run: sf code-analyzer rules --rule-selector eslint
161
+
162
+ Search output for keywords
163
+
164
+ ├─ Built-in rule found? → Configure it (Tier 1) → DONE ✅
165
+
166
+ ├─ Pattern is "ban function X"? → Use no-restricted-globals (Tier 2) → DONE ✅
167
+
168
+ ├─ Pattern is "ban syntax Y"? → Use no-restricted-syntax (Tier 2) → DONE ✅
169
+
170
+ └─ Complex multi-node pattern? → Create custom plugin (Tier 3) → See eslint-custom-plugins.md
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Key Rules
176
+
177
+ 1. **ALWAYS run discovery FIRST** — 90% of requests are Tier 1 or Tier 2
178
+ 2. **NEVER create a custom plugin without checking built-in rules** — this is a skill failure
179
+ 3. **VALIDATE after configuration** — `sf code-analyzer rules --rule-selector eslint:<name>` must show the rule
180
+ 4. **TEST both positive and negative samples** — confirm violations are caught AND clean code passes
181
+
182
+ ---
183
+
184
+ ## When to Read Other References
185
+
186
+ - **All ESLint requests start here** (discovery)
187
+ - **If Tier 3 custom plugin needed:** Read `references/eslint-custom-plugins.md`
188
+ - **If troubleshooting config issues:** Read `references/troubleshooting.md` (ESLint section)
@@ -0,0 +1,114 @@
1
+ # ESLint Tier 2: Configurable Rules
2
+
3
+ [← Back to ESLint Rules Discovery](eslint-rules-discovery.md)
4
+
5
+ ## Tier 2: Configurable Rules
6
+
7
+ When no built-in rule exists but the pattern is generic (ban a function, ban a property, ban a syntax construct):
8
+
9
+ ### Option A: `no-restricted-globals`
10
+
11
+ Ban specific global functions or variables.
12
+
13
+ **Example: Ban setTimeout/setInterval**
14
+ ```javascript
15
+ // eslint.config.js
16
+ module.exports = [
17
+ {
18
+ files: ["**/lwc/**/*.js"],
19
+ rules: {
20
+ "no-restricted-globals": ["error",
21
+ {
22
+ name: "setTimeout",
23
+ message: "Use LWC lifecycle hooks instead of setTimeout"
24
+ },
25
+ {
26
+ name: "setInterval",
27
+ message: "Use LWC lifecycle hooks instead of setInterval"
28
+ }
29
+ ]
30
+ }
31
+ }
32
+ ];
33
+ ```
34
+
35
+ **Example: Ban window.localStorage**
36
+ ```javascript
37
+ rules: {
38
+ "no-restricted-globals": ["error",
39
+ {
40
+ name: "localStorage",
41
+ message: "Use Salesforce state management instead of localStorage"
42
+ }
43
+ ]
44
+ }
45
+ ```
46
+
47
+ ### Option B: `no-restricted-syntax`
48
+
49
+ Ban specific AST patterns using ESLint selectors.
50
+
51
+ **Example: Ban eval() calls**
52
+ ```javascript
53
+ rules: {
54
+ "no-restricted-syntax": ["error",
55
+ {
56
+ selector: "CallExpression[callee.name='eval']",
57
+ message: "eval() is forbidden for security reasons"
58
+ }
59
+ ]
60
+ }
61
+ ```
62
+
63
+ **Example: Ban innerHTML property access**
64
+ ```javascript
65
+ rules: {
66
+ "no-restricted-syntax": ["error",
67
+ {
68
+ selector: "MemberExpression[property.name='innerHTML']",
69
+ message: "innerHTML is forbidden - use textContent or render() for XSS prevention"
70
+ }
71
+ ]
72
+ }
73
+ ```
74
+
75
+ **Example: Ban for-in loops**
76
+ ```javascript
77
+ rules: {
78
+ "no-restricted-syntax": ["error",
79
+ {
80
+ selector: "ForInStatement",
81
+ message: "for-in loops are forbidden - use for-of or Object.keys()"
82
+ }
83
+ ]
84
+ }
85
+ ```
86
+
87
+ #### ESLint Selector Syntax Cheat Sheet
88
+
89
+ | Pattern | Selector | Example |
90
+ |---|---|---|
91
+ | Function call | `CallExpression[callee.name='functionName']` | `eval()`, `alert()` |
92
+ | Property access | `MemberExpression[property.name='propName']` | `obj.innerHTML` |
93
+ | Statement type | `ForInStatement`, `WithStatement` | for-in, with statements |
94
+ | Operator | `BinaryExpression[operator='==']` | `==` instead of `===` |
95
+ | Literal value | `Literal[value='string']` | Specific string literals |
96
+
97
+ **Full selector docs:** https://eslint.org/docs/latest/extend/selectors
98
+
99
+ ### Option C: `no-restricted-properties`
100
+
101
+ Ban specific object properties.
102
+
103
+ **Example: Ban Object.prototype methods**
104
+ ```javascript
105
+ rules: {
106
+ "no-restricted-properties": ["error",
107
+ {
108
+ object: "Object",
109
+ property: "setPrototypeOf",
110
+ message: "setPrototypeOf is forbidden for performance reasons"
111
+ }
112
+ ]
113
+ }
114
+ ```
@@ -0,0 +1,113 @@
1
+ # ESLint Tier 3: Custom Plugins
2
+
3
+ [← Back to ESLint Rules Discovery](eslint-rules-discovery.md)
4
+
5
+ ## Tier 3: Custom Plugins (LAST RESORT)
6
+
7
+ Only create a custom ESLint plugin when:
8
+ - ❌ No built-in rule exists (checked Tier 1)
9
+ - ❌ No configurable rule can express the pattern (checked Tier 2 — see [eslint-tier2-configurable.md](eslint-tier2-configurable.md))
10
+ - ✅ The pattern requires checking multiple AST nodes with complex logic
11
+ - ✅ The pattern is domain-specific to your codebase
12
+
13
+ **Examples that justify custom plugins:**
14
+ - "Flag LWC components with @api properties but no input validation in connectedCallback"
15
+ - "Detect imperative Apex calls without error handling (import + .then() without .catch())"
16
+ - "Enforce naming conventions on specific decorator patterns"
17
+
18
+ **See:** [eslint-custom-plugins.md](eslint-custom-plugins.md) for the plugin creation guide.
19
+
20
+ ---
21
+
22
+ ## Tier-by-Tier Worked Examples
23
+
24
+ Tier 2 worked examples (banning globals, restricting syntax, restricting properties) live in [eslint-tier2-configurable.md](eslint-tier2-configurable.md). The examples below cover Tier 1 (built-in rules and the LWC plugin) so the discovery → configure → validate flow is documented end-to-end.
25
+
26
+ ### Example 1: "Ban console.log" (Tier 1 — built-in)
27
+
28
+ **User Request:** "Create a rule to ban console.log in LWC"
29
+
30
+ **Discovery:**
31
+ ```bash
32
+ $ sf code-analyzer rules --rule-selector eslint | grep -i console
33
+ eslint:no-console disallow the use of console
34
+ ```
35
+
36
+ **Result:** Built-in rule exists. ✅
37
+
38
+ **Configuration:**
39
+ ```javascript
40
+ // eslint.config.js
41
+ module.exports = [
42
+ {
43
+ files: ["**/lwc/**/*.js"],
44
+ rules: {
45
+ "no-console": "error"
46
+ }
47
+ }
48
+ ];
49
+ ```
50
+
51
+ **Validation:**
52
+ ```bash
53
+ sf code-analyzer rules --rule-selector eslint:no-console
54
+ # Should show: eslint:no-console | error | ...
55
+ ```
56
+
57
+ **Test:**
58
+ ```bash
59
+ sf code-analyzer run --rule-selector eslint:no-console --target lwc/
60
+ ```
61
+
62
+ ---
63
+
64
+ ### Example 2: "Ban innerHTML" (Tier 1 — LWC plugin)
65
+
66
+ **User Request:** "Ban innerHTML in LWC for XSS prevention"
67
+
68
+ **Discovery:**
69
+ ```bash
70
+ $ sf code-analyzer rules --rule-selector eslint | grep -i inner
71
+ @lwc/lwc/no-inner-html disallow use of innerHTML
72
+ ```
73
+
74
+ **Result:** LWC plugin rule exists. ✅
75
+
76
+ **Configuration:**
77
+ ```javascript
78
+ // eslint.config.js
79
+ module.exports = [
80
+ {
81
+ files: ["**/lwc/**/*.js"],
82
+ rules: {
83
+ "@lwc/lwc/no-inner-html": "error"
84
+ }
85
+ }
86
+ ];
87
+ ```
88
+
89
+ **Validation:**
90
+ ```bash
91
+ sf code-analyzer rules --rule-selector eslint:@lwc/lwc/no-inner-html
92
+ ```
93
+
94
+ ---
95
+
96
+ ### Example 3: "Enforce === over ==" (Tier 1 — built-in)
97
+
98
+ **User Request:** "Enforce strict equality checks"
99
+
100
+ **Discovery:**
101
+ ```bash
102
+ $ sf code-analyzer rules --rule-selector eslint | grep -i equal
103
+ eslint:eqeqeq require the use of === and !==
104
+ ```
105
+
106
+ **Result:** Built-in rule `eqeqeq` exists. ✅
107
+
108
+ **Configuration:**
109
+ ```javascript
110
+ rules: {
111
+ "eqeqeq": ["error", "always"]
112
+ }
113
+ ```
@@ -0,0 +1,285 @@
1
+ # Metadata XML Rules (PMD with language="xml")
2
+
3
+ Write PMD XPath rules that target Salesforce metadata XML files (`.field-meta.xml`, `.permissionset-meta.xml`, `.profile-meta.xml`, `.flow-meta.xml`, etc.) to enforce org governance.
4
+
5
+ ## How It Works
6
+
7
+ PMD's `language="xml"` mode parses any XML file into a DOM-like AST. You write XPath expressions against element/attribute names in the XML structure — same mechanism as Apex rules, but the AST is the XML DOM.
8
+
9
+ ## Critical: PMD 7 XML XPath Rules
10
+
11
+ ### Rule 1: Namespace — use `local-name()`
12
+
13
+ Salesforce metadata files declare a namespace:
14
+ ```xml
15
+ <?xml version="1.0" encoding="UTF-8"?>
16
+ <CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
17
+ <fullName>My_Field__c</fullName>
18
+ ...
19
+ </CustomField>
20
+ ```
21
+
22
+ This namespace **breaks standard XPath** because `//fullName` won't match — PMD sees it as `//metadata:fullName` internally.
23
+
24
+ **Solution:** Use `local-name()` to match element names regardless of namespace:
25
+
26
+ ```xpath
27
+ //*[local-name()='CustomField']/*[local-name()='fullName']
28
+ ```
29
+
30
+ **This applies to ALL Salesforce metadata XPath rules.** Never use bare element names without `local-name()`.
31
+
32
+ ### Rule 2: Text content — use `@Text` (NOT `text()`)
33
+
34
+ ⚠️ **PMD 7's XML language does NOT support `text()` for value comparison.** The `text()` function returns 0 matches regardless of content. This is a PMD 7 change from PMD 6.
35
+
36
+ **Use the `@Text` attribute instead:**
37
+
38
+ ```xpath
39
+ // ❌ WRONG — does not work in PMD 7:
40
+ //*[local-name()='name'][text()='ModifyAllData']
41
+
42
+ // ✅ CORRECT — use @Text attribute:
43
+ //*[@Text='ModifyAllData']
44
+ ```
45
+
46
+ ### Rule 3: Navigation — text nodes require `../..`
47
+
48
+ In PMD 7 XML, `@Text` matches TEXT NODES (child nodes of elements), not the elements themselves. To navigate from a matched text node to its parent element hierarchy:
49
+
50
+ ```xpath
51
+ // @Text='ModifyAllData' matches the TEXT NODE inside <name>ModifyAllData</name>
52
+ // To get the <name> element: go up one level
53
+ //*[@Text='ModifyAllData']/..
54
+
55
+ // To get the <userPermissions> parent: go up two levels
56
+ //*[@Text='ModifyAllData']/../..
57
+
58
+ // To check a sibling's text value from the parent:
59
+ //*[@Text='ModifyAllData']/../..[.//*[@Text='true']]
60
+ ```
61
+
62
+ ### Complete Pattern for Checking Parent + Sibling Text Values
63
+
64
+ The canonical PMD 7 pattern for "find element X that contains child with text A AND child with text B":
65
+
66
+ ```xpath
67
+ //*[@Text='TargetValue']/../..
68
+ [local-name()='ParentElement']
69
+ [.//*[@Text='ConditionValue']]
70
+ ```
71
+
72
+ Example — find `userPermissions` where name=ModifyAllData AND enabled=true:
73
+ ```xpath
74
+ //*[@Text='ModifyAllData']/../..
75
+ [local-name()='userPermissions']
76
+ [.//*[@Text='true']]
77
+ ```
78
+
79
+ ## AST Dump for Metadata Files
80
+
81
+ Dump the AST to see the exact XML structure:
82
+ ```bash
83
+ sf code-analyzer ast-dump --file force-app/main/default/objects/Account/fields/MyField__c.field-meta.xml --language xml
84
+ ```
85
+
86
+ The output shows the DOM tree — element nodes, text nodes, and attributes. Use this to confirm element names before writing XPath.
87
+
88
+ ## Ruleset XML Template for Metadata Rules
89
+
90
+ ```xml
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <ruleset name="MetadataGovernanceRules"
93
+ xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
94
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
95
+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
96
+
97
+ <description>Custom rules for Salesforce metadata governance</description>
98
+
99
+ <rule name="MyMetadataRule"
100
+ language="xml"
101
+ message="Violation message here"
102
+ class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
103
+
104
+ <description>What this rule enforces</description>
105
+ <priority>3</priority>
106
+
107
+ <properties>
108
+ <property name="xpath">
109
+ <value><![CDATA[
110
+ //*[local-name()='YourElement'][your-condition]
111
+ ]]></value>
112
+ </property>
113
+ </properties>
114
+ </rule>
115
+ </ruleset>
116
+ ```
117
+
118
+ ## Configuration
119
+
120
+ ```yaml
121
+ # code-analyzer.yml
122
+ engines:
123
+ pmd:
124
+ custom_rulesets:
125
+ - "custom-rules/metadata-governance.xml"
126
+ file_extensions:
127
+ xml: [".xml"]
128
+ ```
129
+
130
+ ⚠️ **IMPORTANT:** PMD's XML language only scans `.xml` files by default. You MUST add `file_extensions: { xml: [".xml"] }` under `engines.pmd` in your config. This single entry covers ALL Salesforce metadata compound extensions (`.permissionset-meta.xml`, `.field-meta.xml`, `.flow-meta.xml`, etc.) because the system reads the final `.xml` portion of the filename.
131
+
132
+ ⚠️ **Do NOT add compound extensions** like `.permissionset-meta.xml` to the list — Code Analyzer's validator only accepts single-segment extensions matching `/^[.][a-zA-Z0-9]+$/` and will reject them with a config error.
133
+
134
+ ## Common Metadata File Structures
135
+
136
+ ### Custom Field (`.field-meta.xml`)
137
+ ```xml
138
+ <CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
139
+ <fullName>Revenue__c</fullName>
140
+ <label>Revenue</label>
141
+ <type>Currency</type>
142
+ <required>false</required>
143
+ <description>Annual revenue</description>
144
+ </CustomField>
145
+ ```
146
+
147
+ ### Permission Set (`.permissionset-meta.xml`)
148
+ ```xml
149
+ <PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
150
+ <label>Admin Access</label>
151
+ <userPermissions>
152
+ <enabled>true</enabled>
153
+ <name>ModifyAllData</name>
154
+ </userPermissions>
155
+ <fieldPermissions>
156
+ <editable>true</editable>
157
+ <field>Account.Revenue__c</field>
158
+ <readable>true</readable>
159
+ </fieldPermissions>
160
+ </PermissionSet>
161
+ ```
162
+
163
+ ### Profile (`.profile-meta.xml`)
164
+ ```xml
165
+ <Profile xmlns="http://soap.sforce.com/2006/04/metadata">
166
+ <userPermissions>
167
+ <enabled>true</enabled>
168
+ <name>ViewSetup</name>
169
+ </userPermissions>
170
+ <fieldPermissions>
171
+ <editable>true</editable>
172
+ <field>Account.SSN__c</field>
173
+ </fieldPermissions>
174
+ </Profile>
175
+ ```
176
+
177
+ ### Flow (`.flow-meta.xml`)
178
+ ```xml
179
+ <Flow xmlns="http://soap.sforce.com/2006/04/metadata">
180
+ <apiVersion>58.0</apiVersion>
181
+ <label>My Flow</label>
182
+ <processType>AutoLaunchedFlow</processType>
183
+ <status>Active</status>
184
+ <processMetadataValues>
185
+ <name>CanvasMode</name>
186
+ <value><stringValue>AUTO_LAYOUT_CANVAS</stringValue></value>
187
+ </processMetadataValues>
188
+ <recordCreates>
189
+ <name>Create_Account</name>
190
+ <object>Account</object>
191
+ </recordCreates>
192
+ <loops>
193
+ <name>Loop_Records</name>
194
+ <collectionReference>Get_Records</collectionReference>
195
+ </loops>
196
+ </Flow>
197
+ ```
198
+
199
+ ## XPath Patterns for Metadata (PMD 7)
200
+
201
+ All patterns below use `@Text` for text content matching (NOT `text()` which is broken in PMD 7).
202
+
203
+ ### Require description on Custom Fields
204
+
205
+ **Missing description entirely:**
206
+ ```xpath
207
+ //*[local-name()='CustomField'][not(*[local-name()='description'])]
208
+ ```
209
+
210
+ **Missing OR empty description (catches `<description></description>` too):**
211
+ ```xpath
212
+ //*[local-name()='CustomField'][not(*[local-name()='description']) or *[local-name()='description'][not(.//*[@Text])]]
213
+ ```
214
+ Note: `.//*[@Text]` checks for any descendant text node with content. Do NOT put `[not(@Text)]` directly on the `<description>` element — `@Text` only exists on child text nodes, not on elements themselves. Putting it on the element always evaluates to true (false positive).
215
+
216
+ ### Flag ModifyAllData / ViewAllData in Permission Sets
217
+ ```xpath
218
+ //*[@Text='ModifyAllData' or @Text='ViewAllData']/../..
219
+ [local-name()='userPermissions']
220
+ [.//*[@Text='true']]
221
+ ```
222
+
223
+ ### Enforce minimum API version (60.0+)
224
+ ```xpath
225
+ //*[local-name()='apiVersion']/*[number(@Text) < 60]
226
+ ```
227
+ Note: `/*` navigates to the **child text node** where `@Text` lives. Do NOT put `@Text` directly on the element — it won't match because `@Text` only exists on text nodes (children), not on elements themselves.
228
+
229
+ ### Flag field permissions in Profiles (should be in Perm Sets)
230
+ ```xpath
231
+ //*[local-name()='Profile']/*[local-name()='fieldPermissions']
232
+ ```
233
+ (No text matching needed — structural only.)
234
+
235
+ ### Flag dangerous permissions (ModifyAllData only, enabled)
236
+ ```xpath
237
+ //*[@Text='ModifyAllData']/../..
238
+ [local-name()='userPermissions']
239
+ [.//*[@Text='true']]
240
+ ```
241
+
242
+ ### Flag DML (recordCreates/recordUpdates/recordDeletes) inside Flow loops
243
+ ```xpath
244
+ //*[local-name()='loops'][
245
+ following-sibling::*[local-name()='recordCreates' or local-name()='recordUpdates' or local-name()='recordDeletes']
246
+ ]
247
+ ```
248
+ (No text matching needed — structural only.)
249
+
250
+ ## Targeting Specific File Types
251
+
252
+ PMD only scans `.xml` files by default. You must add `.xml` to the config. This single extension covers ALL Salesforce compound metadata extensions (`.permissionset-meta.xml`, `.field-meta.xml`, etc.) because `path.extname()` returns `.xml` from these filenames.
253
+
254
+ ```yaml
255
+ # code-analyzer.yml
256
+ engines:
257
+ pmd:
258
+ file_extensions:
259
+ xml: [".xml"]
260
+ ```
261
+
262
+ ⚠️ Do NOT add compound extensions — the validator rejects anything that doesn't match `/^[.][a-zA-Z0-9]+$/`.
263
+
264
+ Additionally, scope your XPath to the correct root element to avoid false positives across file types:
265
+
266
+ ```xpath
267
+ //*[@Text='ModifyAllData']/../..[local-name()='userPermissions']
268
+ [ancestor::*[local-name()='PermissionSet']]
269
+ ```
270
+
271
+ This ensures the rule only fires on permission set files, not on profile or other metadata files.
272
+
273
+ ## Gotchas
274
+
275
+ | Issue | Resolution |
276
+ |-------|------------|
277
+ | XPath matches nothing | Three causes: (1) Forgot `local-name()`. (2) Used `text()` — broken in PMD 7, use `@Text`. (3) File extension not in `file_extensions.xml` config. |
278
+ | Rule fires on wrong metadata type | Add root element scope: `[ancestor::*[local-name()='PermissionSet']]` |
279
+ | Can't match text content | **Use `@Text` attribute** (NOT `text()`). Example: `//*[@Text='ModifyAllData']` |
280
+ | `@Text` matches but parent navigation fails | `@Text` matches TEXT NODES. Go up with `../..`: text→element→parent. |
281
+ | Number comparison fails | `@Text` lives on the **child text node**, NOT on the element. Use: `//*[local-name()='element']/*[number(@Text) < N]` — the `/*` navigates to the text node. Do NOT put `[@Text]` predicate directly on the element (returns 0 matches). |
282
+ | Too many violations on large orgs | Scope with `file_extensions` in PMD config or add `ignores.files` patterns |
283
+ | Rule doesn't fire on metadata files | Add `file_extensions: { xml: [".xml"] }` under `engines.pmd` — this covers all compound extensions. Do NOT add `.permissionset-meta.xml` etc. (validator rejects them). |
284
+ | ast-dump fails with "XmlEncoding" error | Known issue. Read the raw XML file — the file content IS the DOM structure |
285
+ | ast-dump shows different structure | XML AST is the literal DOM — what you see in the file is what you get |