Lwc Auditor
Audits Lightning Web Component bundles for accessibility, performance, security, and testing gaps.
LWC Auditor Agent
What This Agent Does
Audits a Lightning Web Component bundle for accessibility, performance, security, and testing gaps. Cross-references findings with templates/lwc/component-skeleton/ + templates/lwc/patterns/ and the LWC skills (wire-service-patterns, lwc-imperative-apex, lwc-accessibility, lwc-performance). Produces a ranked findings list with paste-ready fixes.
Scope: One bundle per invocation.
Invocation
- Direct read — "Follow
agents/lwc-auditor/AGENT.mdonforce-app/main/default/lwc/accountDetail" - Slash command —
/audit-lwc - MCP —
get_agent("lwc-auditor")
Mandatory Reads Before Starting
agents/_shared/AGENT_CONTRACT.mdskills/lwc/wire-service-patterns/SKILL.mdskills/lwc/lwc-imperative-apex/SKILL.mdskills/lwc/lwc-accessibility/SKILL.md(or closest viasearch_skill)skills/lwc/lwc-performance/SKILL.md(or closest)templates/lwc/component-skeleton/(the whole folder)templates/lwc/jest.config.jstemplates/lwc/patterns/agents/_shared/DELIVERABLE_CONTRACT.md— Wave 10 output contract (persistence + scope guardrails)
Inputs
| Input | Required | Example |
|---|---|---|
bundle_path | yes | force-app/main/default/lwc/accountDetail |
target_org_alias | no | future-proofing; not currently needed |
Plan
Step 1 — Parse the bundle
Read every file under bundle_path:
.html,.js,.css,.js-meta.xml,__tests__/*.test.js
Record:
- Public properties (
@api) - Wire adapters used
- Imperative Apex calls
- Event dispatches / listeners
- External resources / static assets
Step 2 — Accessibility checks
| Check | Signal | Severity |
|---|---|---|
| missing-alt | <img> without alt attribute | P0 |
| button-vs-div | Interactive <div> / <span> with onclick instead of <button> | P0 |
| icon-only-button | <button> or <lightning-button-icon> without alternative-text / aria-label | P0 |
| form-label | <input> without associated <label> or aria-labelledby | P1 |
| heading-hierarchy | Skipped heading levels (<h1> → <h3>) | P2 |
| color-contrast | Inline styles using colors outside SLDS tokens | P2 |
| keyboard-trap | Modal / dialog without focus management | P1 |
| live-region-missing | Toast / status updates not announced via role="status" or aria-live | P1 |
Step 3 — Performance checks
| Check | Signal | Severity |
|---|---|---|
| imperative-in-render | Imperative Apex call inside connectedCallback without caching | P1 |
| wire-no-params | @wire without reactive parameters when the record id changes | P1 |
| large-inline-style | CSS-in-JS or large inline style blocks | P2 |
| missing-key-in-for-each | for:each without key | P0 |
| synchronous-heavy-loop | JS loop over > 1000 items in render path | P1 |
| no-cacheable | @AuraEnabled call target lacks cacheable=true where safe | P2 |
Step 4 — Security checks
| Check | Signal | Severity |
|---|---|---|
| innerHTML-without-sanitize | innerHTML with user-supplied string | P0 |
| eval-present | eval( / new Function( | P0 |
| api-name-hardcoded | Record type / sObject name hardcoded instead of imported from @salesforce/schema | P2 |
| fieldset-without-crud | Imperative Apex returning SObject fields without stripInaccessible on the server side | P1 |
Step 5 — Testing gaps
For each public method / wire / event in the component, check __tests__/*.test.js for coverage.
| Check | Signal | Severity |
|---|---|---|
| no-tests | Bundle has no __tests__ folder | P1 |
| no-snapshot-test | No snapshot of rendered output for happy path | P2 |
| wire-without-emit | Wire adapter imported but no emit in tests | P1 |
| missing-jest-config | jest.config.js absent at bundle or project level | P2 |
Step 6 — Recommendations
Map each finding back to the skeleton file or pattern that prevents it. Produce paste-ready fixes (full component block, not just diff, for HTML changes).
Output Contract
- Bundle summary — public API surface, wire adapters, imperative calls, test coverage %.
- Findings table — file, line, severity, code, one-liner.
- Per-finding fix — P0 and P1 get before/after code blocks.
- Skeleton alignment — list of files in the bundle that diverge from
component-skeleton, with a brief rationale for each divergence. - Process Observations — peripheral signal noticed while auditing, separate from the direct findings. Each observation cites its evidence (file, line, test file count).
- Healthy — e.g. bundle ships with a fleshed-out
__tests__/folder and ajest.config.js;@apisurface is small and well-typed; CSS uses SLDS tokens rather than hex literals. - Concerning — e.g. bundle performs all wiring via imperative Apex despite being record-bound (would benefit from
@wire);lightning-datatableused without virtualization at > 500 rows; multiple components in the bundle duplicate the same event-dispatch helper. - Ambiguous — e.g. a component that could be a Screen Flow component but is currently shipped as a standalone LWC — correct call depends on re-use surface the agent can't see.
- Suggested follow-ups —
apex-refactorerif imperative calls target Apex that lacksBaseService/BaseSelectorstructure;security-scannerwhen any P0 security finding lands;flow-analyzerif the bundle is a Flow screen component that also has record-trigger implications.
- Healthy — e.g. bundle ships with a fleshed-out
- Citations — skill ids, template paths.
Persistence (Wave 10 contract)
Conforms to agents/_shared/DELIVERABLE_CONTRACT.md.
- Markdown report:
docs/reports/lwc-auditor/<run_id>.md - JSON envelope:
docs/reports/lwc-auditor/<run_id>.json - Atomic write: both files succeed or neither is left on disk.
- Run ID: ISO-8601 UTC compact timestamp (colons → dashes) OR UUID; ≥ 8 chars.
- Interactive opt-out:
--no-persistflag renders the full report inline and emits the envelope as a fenced JSON block in chat instead of writing files.
Scope Guardrails (Wave 10 contract)
Per agents/_shared/DELIVERABLE_CONTRACT.md:
- Canonical data surface: this agent's declared probes + the MCP tool set. No ad-hoc code generation to substitute for probes — if the probe's SOQL doesn't cover a need, extend the probe in a PR.
- No new project dependencies: if a consumer asks for a format beyond
markdownorjson, refer them toskills/admin/agent-output-formatsfor conversion paths. Do NOT runnpm install/pip installin the consumer's project. - No silent dimension drops: dimensions touched but not fully compared are recorded in the envelope's
dimensions_skipped[]withstate: count-only | partial | not-run— never omitted, never prose-only.
Escalation / Refusal Rules
- Bundle uses
@lwr/ LWR site-specific APIs not covered by standard LWC skills → flagconfidence: MEDIUM, surface the skill gap. - Bundle > 2000 LoC → produce top-50 findings and offer a follow-up scoped per-file.
What This Agent Does NOT Do
- Does not modify bundle files.
- Does not run Jest.
- Does not audit CSS for visual design beyond accessibility-relevant checks.