@diegovelasquezweb/a11y-engine 0.1.2 → 0.1.4

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.
@@ -0,0 +1,237 @@
1
+ # CLI Handbook
2
+
3
+ **Navigation**: [Home](../README.md) • [Architecture](architecture.md) • [CLI Handbook](cli-handbook.md) • [Output Artifacts](outputs.md)
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Basic usage](#basic-usage)
10
+ - [Prerequisites](#prerequisites)
11
+ - [Flag groups](#flag-groups)
12
+ - [Targeting & scope](#targeting--scope)
13
+ - [Audit intelligence](#audit-intelligence)
14
+ - [Execution & emulation](#execution--emulation)
15
+ - [Output generation](#output-generation)
16
+ - [Examples](#examples)
17
+ - [Exit codes](#exit-codes)
18
+
19
+ ---
20
+
21
+ ## Basic usage
22
+
23
+ ```bash
24
+ npx a11y-audit --base-url <url> [options]
25
+ ```
26
+
27
+ Or if installed locally:
28
+
29
+ ```bash
30
+ node node_modules/@diegovelasquezweb/a11y-engine/scripts/audit.mjs --base-url <url> [options]
31
+ ```
32
+
33
+ The only required flag is `--base-url`. All other flags are optional.
34
+
35
+ ---
36
+
37
+ ## Prerequisites
38
+
39
+ The engine uses two separate browser installations:
40
+
41
+ ```bash
42
+ # Required — used by axe-core and CDP checks
43
+ npx playwright install chromium
44
+
45
+ # Required for pa11y — uses Puppeteer's Chrome (separate from Playwright)
46
+ npx puppeteer browsers install chrome
47
+ ```
48
+
49
+ If Puppeteer Chrome is missing, pa11y checks fail silently (non-fatal) and the scan continues with axe-core + CDP only.
50
+
51
+ ---
52
+
53
+ ## Flag groups
54
+
55
+ ### Targeting & scope
56
+
57
+ Controls what gets scanned.
58
+
59
+ | Flag | Argument | Default | Description |
60
+ | :--- | :--- | :--- | :--- |
61
+ | `--base-url` | `<url>` | (Required) | Starting URL. Must include protocol (`https://` or `http://`). |
62
+ | `--max-routes` | `<num>` | `10` | Maximum unique same-origin paths to discover and scan. |
63
+ | `--crawl-depth` | `<num>` | `2` | How deep to follow links during BFS discovery (1-3). Has no effect when `--routes` is set. |
64
+ | `--routes` | `<csv>` | — | Explicit paths to scan (e.g. `/,/about,/contact`). Overrides auto-discovery entirely. |
65
+ | `--project-dir` | `<path>` | — | Path to the audited project source. Enables the source code pattern scanner and framework auto-detection from `package.json`. |
66
+
67
+ **Route discovery logic**:
68
+ 1. If the target has a `sitemap.xml`, all listed URLs are used (up to `--max-routes`).
69
+ 2. Otherwise, BFS crawl from `--base-url`, following same-origin `<a href>` links.
70
+ 3. `--routes` always takes precedence over both.
71
+
72
+ ---
73
+
74
+ ### Audit intelligence
75
+
76
+ Controls how findings are interpreted and filtered.
77
+
78
+ | Flag | Argument | Default | Description |
79
+ | :--- | :--- | :--- | :--- |
80
+ | `--target` | `<text>` | `WCAG 2.2 AA` | Compliance target label rendered in reports. Does not change which rules run. |
81
+ | `--only-rule` | `<id>` | — | Run a single axe rule ID only. Useful for focused re-audits after fixing a specific issue. |
82
+ | `--ignore-findings` | `<csv>` | — | Comma-separated list of axe rule IDs to suppress from output entirely. |
83
+ | `--exclude-selectors` | `<csv>` | — | CSS selectors to skip. Elements matching these selectors are excluded from axe scanning. |
84
+ | `--axe-tags` | `<csv>` | `wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22a,wcag22aa` | axe-core WCAG tag filter. Also determines the pa11y standard (`WCAG2A`, `WCAG2AA`, or `WCAG2AAA`). |
85
+ | `--framework` | `<name>` | — | Override auto-detected framework. Affects which fix notes and source boundaries are applied. |
86
+
87
+ **Supported `--framework` values**: `nextjs`, `gatsby`, `react`, `nuxt`, `vue`, `angular`, `astro`, `svelte`, `shopify`, `wordpress`, `drupal`.
88
+
89
+ ---
90
+
91
+ ### Execution & emulation
92
+
93
+ Controls browser behavior during scanning.
94
+
95
+ | Flag | Argument | Default | Description |
96
+ | :--- | :--- | :--- | :--- |
97
+ | `--color-scheme` | `light\|dark` | `light` | Emulates `prefers-color-scheme` media query. |
98
+ | `--wait-until` | `domcontentloaded\|load\|networkidle` | `domcontentloaded` | Playwright page load strategy. Use `networkidle` for SPAs with async rendering. |
99
+ | `--viewport` | `<WxH>` | `1280x800` | Browser viewport in pixels (e.g. `375x812` for mobile, `1440x900` for desktop). |
100
+ | `--wait-ms` | `<num>` | `2000` | Fixed delay (ms) after page load before the engines run. Useful when JS renders content after `DOMContentLoaded`. |
101
+ | `--timeout-ms` | `<num>` | `30000` | Network timeout per page load (ms). |
102
+ | `--headed` | — | `false` | Launch browser in visible mode. Useful for debugging page rendering issues. |
103
+ | `--affected-only` | — | `false` | Re-scan only routes that had violations in the previous scan. Reads `.audit/a11y-scan-results.json` to determine affected routes. Falls back to full scan if no prior results exist. |
104
+
105
+ ---
106
+
107
+ ### Output generation
108
+
109
+ Controls what artifacts are written.
110
+
111
+ | Flag | Argument | Default | Description |
112
+ | :--- | :--- | :--- | :--- |
113
+ | `--with-reports` | — | `false` | Generate full artifact set: `report.html`, `report.pdf`, `checklist.html`, and `remediation.md`. Requires `--output`. |
114
+ | `--skip-reports` | — | `true` | Default behavior. Only `remediation.md` is generated. |
115
+ | `--output` | `<path>` | — | Absolute or relative path for `report.html`. PDF and checklist are derived from the same directory. |
116
+ | `--skip-patterns` | — | `false` | Disable source code pattern scanner even when `--project-dir` is set. Use this for DOM-only results without static analysis. |
117
+
118
+ ---
119
+
120
+ ## Examples
121
+
122
+ ### Minimal scan
123
+
124
+ ```bash
125
+ # Produces only remediation.md in .audit/
126
+ a11y-audit --base-url https://example.com
127
+ ```
128
+
129
+ ### Full audit with all reports
130
+
131
+ ```bash
132
+ a11y-audit \
133
+ --base-url https://example.com \
134
+ --with-reports \
135
+ --output ./audit/report.html
136
+ ```
137
+
138
+ ### Include source code intelligence
139
+
140
+ ```bash
141
+ a11y-audit \
142
+ --base-url http://localhost:3000 \
143
+ --project-dir . \
144
+ --with-reports \
145
+ --output ./audit/report.html
146
+ ```
147
+
148
+ ### Focused re-audit — single rule, single route
149
+
150
+ ```bash
151
+ a11y-audit \
152
+ --base-url https://example.com \
153
+ --only-rule color-contrast \
154
+ --routes /checkout \
155
+ --max-routes 1
156
+ ```
157
+
158
+ ### Fast re-audit after applying fixes
159
+
160
+ ```bash
161
+ # Only re-scans routes that had violations in the last run
162
+ a11y-audit --base-url https://example.com --affected-only
163
+ ```
164
+
165
+ ### SPA with deferred rendering
166
+
167
+ ```bash
168
+ a11y-audit \
169
+ --base-url https://example.com \
170
+ --wait-until networkidle \
171
+ --wait-ms 3000
172
+ ```
173
+
174
+ ### Dark mode audit
175
+
176
+ ```bash
177
+ a11y-audit --base-url https://example.com --color-scheme dark
178
+ ```
179
+
180
+ ### Mobile viewport
181
+
182
+ ```bash
183
+ a11y-audit --base-url https://example.com --viewport 375x812
184
+ ```
185
+
186
+ ### Suppress known false positives
187
+
188
+ ```bash
189
+ a11y-audit \
190
+ --base-url https://example.com \
191
+ --ignore-findings color-contrast,frame-title
192
+ ```
193
+
194
+ ### Explicit route list
195
+
196
+ ```bash
197
+ a11y-audit \
198
+ --base-url https://example.com \
199
+ --routes /,/pricing,/blog,/contact
200
+ ```
201
+
202
+ ### Override framework detection
203
+
204
+ ```bash
205
+ a11y-audit \
206
+ --base-url http://localhost:3000 \
207
+ --framework nextjs \
208
+ --project-dir .
209
+ ```
210
+
211
+ ### Custom axe-core WCAG tags
212
+
213
+ ```bash
214
+ # Only WCAG 2.0 A checks
215
+ a11y-audit --base-url https://example.com --axe-tags wcag2a
216
+
217
+ # Include AAA checks
218
+ a11y-audit --base-url https://example.com --axe-tags wcag2a,wcag2aa,wcag2aaa
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Exit codes
224
+
225
+ | Code | Meaning |
226
+ | :--- | :--- |
227
+ | `0` | Audit completed successfully (regardless of findings count) |
228
+ | `1` | Runtime error — invalid URL, missing required flag, stage failure, or timeout |
229
+
230
+ The engine never exits `1` just because findings were found. Exit `1` only indicates a pipeline or configuration error.
231
+
232
+ **Stdout markers** (parseable by scripts and CI):
233
+
234
+ ```
235
+ REMEDIATION_PATH=<abs-path> # always printed on success
236
+ REPORT_PATH=<abs-path> # only printed when --with-reports is set
237
+ ```
@@ -0,0 +1,303 @@
1
+ # Output Artifacts
2
+
3
+ **Navigation**: [Home](../README.md) • [Architecture](architecture.md) • [CLI Handbook](cli-handbook.md) • [Output Artifacts](outputs.md)
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Default output directory](#default-output-directory)
10
+ - [progress.json](#progressjson)
11
+ - [a11y-scan-results.json](#a11y-scan-resultsjson)
12
+ - [a11y-findings.json](#a11y-findingsjson)
13
+ - [remediation.md](#remediationmd)
14
+ - [report.html](#reporthtml)
15
+ - [report.pdf](#reportpdf)
16
+ - [checklist.html](#checklisthtml)
17
+ - [Consuming outputs programmatically](#consuming-outputs-programmatically)
18
+
19
+ ---
20
+
21
+ ## Default output directory
22
+
23
+ All artifacts are written to `.audit/` relative to the package root (`SKILL_ROOT`). When consumed as an npm package, this resolves to the real package path inside `node_modules/`.
24
+
25
+ ```
26
+ .audit/
27
+ ├── progress.json # real-time scan progress (per-engine steps + counts)
28
+ ├── a11y-scan-results.json # merged raw results from axe + CDP + pa11y
29
+ ├── a11y-findings.json # enriched findings (primary data artifact)
30
+ ├── remediation.md # AI agent remediation guide
31
+ ├── report.html # interactive dashboard (--with-reports)
32
+ ├── report.pdf # compliance report (--with-reports)
33
+ ├── checklist.html # manual testing checklist (--with-reports)
34
+ └── screenshots/ # element screenshots per violation
35
+ ```
36
+
37
+ > When integrating the engine as a dependency (e.g. in `a11y-scanner`), use `fs.realpathSync` on the symlink path to resolve the real `.audit/` location — pnpm uses a deep `.pnpm/` directory structure, not the `node_modules/@scope/pkg` symlink.
38
+
39
+ ---
40
+
41
+ ## progress.json
42
+
43
+ Real-time scan progress written by `scripts/engine/dom-scanner.mjs` as each engine runs. Used by integrations for live progress UI.
44
+
45
+ ```json
46
+ {
47
+ "steps": {
48
+ "page": { "status": "done", "updatedAt": "2026-03-14T14:02:50.609Z" },
49
+ "axe": { "status": "done", "updatedAt": "2026-03-14T14:02:51.389Z", "found": 8 },
50
+ "cdp": { "status": "done", "updatedAt": "2026-03-14T14:02:51.401Z", "found": 3 },
51
+ "pa11y": { "status": "done", "updatedAt": "2026-03-14T14:02:55.667Z", "found": 2 },
52
+ "merge": { "status": "done", "updatedAt": "2026-03-14T14:02:55.668Z", "axe": 8, "cdp": 3, "pa11y": 2, "merged": 11 }
53
+ },
54
+ "currentStep": "merge"
55
+ }
56
+ ```
57
+
58
+ ### Step keys
59
+
60
+ | Key | Engine | Description |
61
+ | :--- | :--- | :--- |
62
+ | `page` | — | Page navigation and load |
63
+ | `axe` | axe-core | axe-core WCAG rule scan. `found` = violation count. |
64
+ | `cdp` | CDP | Chrome DevTools Protocol accessibility tree check. `found` = issue count. |
65
+ | `pa11y` | pa11y | HTML CodeSniffer scan. `found` = issue count. |
66
+ | `merge` | — | Cross-engine merge and deduplication. `merged` = final unique count. |
67
+
68
+ ### Step statuses
69
+
70
+ `pending` → `running` → `done` (or `error`)
71
+
72
+ ---
73
+
74
+ ## a11y-scan-results.json
75
+
76
+ Merged results from all three engines (axe-core + CDP + pa11y) per route. Written by `scripts/engine/dom-scanner.mjs`.
77
+
78
+ ```json
79
+ {
80
+ "generated_at": "2026-03-14T14:02:55.668Z",
81
+ "base_url": "https://example.com",
82
+ "projectContext": { "framework": "nextjs", "uiLibraries": ["radix-ui"] },
83
+ "routes": [
84
+ {
85
+ "path": "/",
86
+ "url": "https://example.com/",
87
+ "violations": [...],
88
+ "incomplete": [...],
89
+ "passes": [...]
90
+ }
91
+ ]
92
+ }
93
+ ```
94
+
95
+ Each violation in the `violations` array includes a `source` field indicating which engine produced it (`undefined` for axe-core, `"cdp"` for CDP checks, `"pa11y"` for pa11y).
96
+
97
+ This file is consumed by `analyzer.mjs` and also used by `--affected-only` to determine which routes to re-scan on subsequent runs.
98
+
99
+ ---
100
+
101
+ ## a11y-findings.json
102
+
103
+ The primary enriched data artifact. Written by `scripts/engine/analyzer.mjs`. This is the file consumed by all report builders.
104
+
105
+ ### Top-level structure
106
+
107
+ ```json
108
+ {
109
+ "metadata": { ... },
110
+ "findings": [ ... ],
111
+ "incomplete_findings": [ ... ]
112
+ }
113
+ ```
114
+
115
+ ### `metadata` fields
116
+
117
+ | Field | Type | Description |
118
+ | :--- | :--- | :--- |
119
+ | `scanDate` | `string` (ISO 8601) | Timestamp of when the scan ran |
120
+ | `checklist` | `object` | Manual check results if checklist was run |
121
+ | `projectContext` | `object` | Auto-detected framework, CMS, and UI libraries |
122
+ | `overallAssessment` | `string` | `"Pass"`, `"Conditional Pass"`, or `"Fail"` |
123
+ | `passedCriteria` | `string[]` | WCAG criterion IDs with no active violations |
124
+ | `outOfScope` | `object[]` | Findings excluded due to guardrails |
125
+ | `recommendations` | `object[]` | Grouped fix recommendations by component |
126
+ | `testingMethodology` | `object` | Scan scope and methodology summary |
127
+ | `fpFiltered` | `number` | Count of findings filtered as likely false positives |
128
+ | `deduplicatedCount` | `number` | Count of duplicate findings removed |
129
+
130
+ ### `findings` — per-finding fields
131
+
132
+ | Field | Type | Description |
133
+ | :--- | :--- | :--- |
134
+ | `id` | `string` | Deterministic finding ID (e.g. `A11Y-001`) |
135
+ | `rule_id` | `string` | Rule ID from the source engine (e.g. `color-contrast`, `cdp-missing-accessible-name`, `pa11y-wcag2aa-...`) |
136
+ | `source_rule_id` | `string\|null` | Original rule ID when mapped from CDP/pa11y to axe equivalent |
137
+ | `title` | `string` | Human-readable finding title |
138
+ | `severity` | `string` | `Critical`, `Serious`, `Moderate`, or `Minor` |
139
+ | `wcag` | `string` | WCAG success criterion (e.g. `1.4.3`) |
140
+ | `wcag_criterion_id` | `string` | Full WCAG criterion ID (e.g. `1.4.3`) |
141
+ | `wcag_classification` | `string` | `A`, `AA`, `AAA`, or `Best Practice` |
142
+ | `area` | `string` | Affected page area (e.g. `Navigation`, `Forms`) |
143
+ | `url` | `string` | URL where the violation was found |
144
+ | `selector` | `string` | CSS selector for the affected element |
145
+ | `primary_selector` | `string` | Most stable selector chosen by the analyzer |
146
+ | `impacted_users` | `string` | Disability groups affected |
147
+ | `actual` | `string` | Observed violation description |
148
+ | `expected` | `string` | What the correct behavior should be |
149
+ | `category` | `string` | Violation category (e.g. `Color & Contrast`) |
150
+ | `primary_failure_mode` | `string\|null` | Root cause classification |
151
+ | `relationship_hint` | `string\|null` | Label/input relationship context |
152
+ | `failure_checks` | `object[]` | Engine check-level failure details |
153
+ | `related_context` | `object[]` | Surrounding DOM context |
154
+ | `fix_description` | `string\|null` | Plain-language fix explanation |
155
+ | `fix_code` | `string\|null` | Ready-to-apply code snippet |
156
+ | `fix_code_lang` | `string` | Language for code block (e.g. `html`, `jsx`) |
157
+ | `recommended_fix` | `string` | Link to canonical fix reference (APG, MDN) |
158
+ | `mdn` | `string\|null` | MDN documentation URL |
159
+ | `effort` | `string\|null` | Fix effort estimate (`low`, `medium`, `high`) |
160
+ | `related_rules` | `string[]` | Related rule IDs |
161
+ | `guardrails` | `object\|null` | Agent scope guardrails for this finding |
162
+ | `false_positive_risk` | `string\|null` | Known false positive patterns |
163
+ | `fix_difficulty_notes` | `string\|null` | Edge cases and pitfalls for this fix |
164
+ | `framework_notes` | `string\|null` | Framework-specific fix guidance |
165
+ | `cms_notes` | `string\|null` | CMS-specific fix guidance |
166
+ | `check_data` | `object\|null` | Raw engine check data |
167
+ | `total_instances` | `number` | Count of affected elements across all pages |
168
+ | `evidence` | `object[]` | DOM HTML snippets for each affected element |
169
+ | `screenshot_path` | `string\|null` | Path to element screenshot |
170
+ | `file_search_pattern` | `string\|null` | Regex/glob pattern to find the source file |
171
+ | `managed_by_library` | `string\|null` | UI library managing this element (if any) |
172
+ | `ownership_status` | `string` | `confirmed`, `potential`, or `unknown` |
173
+ | `ownership_reason` | `string\|null` | Why this ownership status was assigned |
174
+ | `primary_source_scope` | `string[]` | Source file paths likely containing the issue |
175
+ | `search_strategy` | `string` | Agent search strategy recommendation |
176
+ | `component_hint` | `string\|null` | Component name hint for source search |
177
+ | `verification_command` | `string\|null` | CLI command to verify fix was applied |
178
+ | `verification_command_fallback` | `string\|null` | Fallback verify command |
179
+ | `pages_affected` | `number\|null` | Number of pages with this violation |
180
+ | `affected_urls` | `string[]\|null` | All URLs where this violation appears |
181
+
182
+ ### `incomplete_findings`
183
+
184
+ Violations that axe-core flagged as "needs review" (not confirmed pass or fail). Included for manual verification but not counted in the compliance score.
185
+
186
+ ---
187
+
188
+ ## remediation.md
189
+
190
+ AI agent-optimized remediation guide. Always generated (even without `--with-reports`). Written to `.audit/remediation.md`.
191
+
192
+ Content:
193
+
194
+ - Audit summary header with score, URL, and date
195
+ - Per-finding sections with: violation description, DOM evidence, fix description, code snippet, verify command, and WCAG criterion
196
+ - "Passed WCAG 2.2 Criteria" section listing clean criteria
197
+ - "Source Code Patterns" section (if source scanner ran)
198
+ - Component grouping table for batching fixes
199
+
200
+ The path is printed to stdout on completion as `REMEDIATION_PATH=<path>`.
201
+
202
+ ---
203
+
204
+ ## report.html
205
+
206
+ Interactive HTML dashboard. Generated only with `--with-reports --output <path>`.
207
+
208
+ Features:
209
+
210
+ - Severity-grouped findings with expandable detail cards
211
+ - DOM evidence with syntax-highlighted code
212
+ - Screenshot thumbnails per finding
213
+ - Search and filter by severity, category, and page
214
+ - Compliance score gauge with grade label
215
+ - Persona impact breakdown (visual, motor, cognitive, etc.)
216
+ - Quick wins section (Critical/Serious findings with ready code)
217
+
218
+ Written to the path specified by `--output`. The path is printed to stdout as `REPORT_PATH=<path>`.
219
+
220
+ ---
221
+
222
+ ## report.pdf
223
+
224
+ Formal PDF compliance report for stakeholders. Generated alongside `report.html` when `--with-reports` is set.
225
+
226
+ Sections:
227
+
228
+ 1. Cover page with score, date, and target URL
229
+ 2. Table of Contents
230
+ 3. Executive Summary — score, overall assessment, finding counts by severity
231
+ 4. Legal Risk Summary — applicable regulations based on score tier
232
+ 5. Methodology — scan scope, tools, and WCAG version
233
+ 6. Findings Breakdown — severity table and issue summary
234
+ 7. Recommended Next Steps — dynamically generated from findings
235
+
236
+ Written to the same directory as `--output` with `.pdf` extension.
237
+
238
+ ---
239
+
240
+ ## checklist.html
241
+
242
+ Interactive manual testing checklist. Generated alongside `report.html` when `--with-reports` is set.
243
+
244
+ Contains the 41 WCAG 2.2 AA manual checks that automated tools cannot detect, including:
245
+
246
+ - Keyboard navigation and focus order
247
+ - Screen reader announcements
248
+ - Motion and animation
249
+ - Zoom and reflow (400%)
250
+ - Cognitive load and reading level
251
+
252
+ Each item is checkable and includes testing instructions. State is not persisted between sessions.
253
+
254
+ Written to the same directory as `--output` as `checklist.html`.
255
+
256
+ ---
257
+
258
+ ## Consuming outputs programmatically
259
+
260
+ ### Reading `a11y-findings.json` from an integration
261
+
262
+ ```js
263
+ import fs from "node:fs";
264
+ import path from "node:path";
265
+ import { createRequire } from "node:module";
266
+
267
+ // Resolve real path (handles pnpm symlinks)
268
+ const req = createRequire(import.meta.url);
269
+ const auditScript = req.resolve("@diegovelasquezweb/a11y-engine/scripts/audit.mjs");
270
+ const engineRoot = path.dirname(path.dirname(auditScript));
271
+ const findingsPath = path.join(engineRoot, ".audit", "a11y-findings.json");
272
+
273
+ const { findings, metadata } = JSON.parse(fs.readFileSync(findingsPath, "utf-8"));
274
+ ```
275
+
276
+ > Note: `import.meta.url` may be mangled by bundlers (e.g. Next.js). In that case, use `fs.realpathSync` on the known symlink instead:
277
+
278
+ ```js
279
+ const symlinkBase = path.join(process.cwd(), "node_modules", "@diegovelasquezweb", "a11y-engine");
280
+ const engineRoot = fs.realpathSync(symlinkBase);
281
+ const findingsPath = path.join(engineRoot, ".audit", "a11y-findings.json");
282
+ ```
283
+
284
+ ### Reading `progress.json` for live UI updates
285
+
286
+ ```js
287
+ const progressPath = path.join(engineRoot, ".audit", "progress.json");
288
+
289
+ // Poll this file during scan execution
290
+ if (fs.existsSync(progressPath)) {
291
+ const progress = JSON.parse(fs.readFileSync(progressPath, "utf-8"));
292
+ console.log(`Current step: ${progress.currentStep}`);
293
+ console.log(`axe found: ${progress.steps?.axe?.found ?? "pending"}`);
294
+ }
295
+ ```
296
+
297
+ ### Parsing stdout markers
298
+
299
+ ```bash
300
+ OUTPUT=$(node scripts/audit.mjs --base-url https://example.com --with-reports --output ./audit/report.html)
301
+ REMEDIATION_PATH=$(echo "$OUTPUT" | grep REMEDIATION_PATH | cut -d= -f2)
302
+ REPORT_PATH=$(echo "$OUTPUT" | grep REPORT_PATH | cut -d= -f2)
303
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegovelasquezweb/a11y-engine",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "WCAG 2.2 AA accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -12,13 +12,19 @@
12
12
  "engines": {
13
13
  "node": ">=18"
14
14
  },
15
+ "exports": {
16
+ ".": "./scripts/index.mjs"
17
+ },
18
+ "main": "scripts/index.mjs",
15
19
  "bin": {
16
20
  "a11y-audit": "scripts/audit.mjs"
17
21
  },
18
22
  "files": [
19
23
  "scripts/**",
20
24
  "assets/**",
25
+ "docs/**",
21
26
  "README.md",
27
+ "CHANGELOG.md",
22
28
  "LICENSE"
23
29
  ],
24
30
  "scripts": {
@@ -33,5 +39,6 @@
33
39
  },
34
40
  "devDependencies": {
35
41
  "vitest": "^4.0.18"
36
- }
42
+ },
43
+ "packageManager": "pnpm@10.22.0+sha512.bf049efe995b28f527fd2b41ae0474ce29186f7edcb3bf545087bd61fbbebb2bf75362d1307fda09c2d288e1e499787ac12d4fcb617a974718a6051f2eee741c"
37
44
  }
package/scripts/audit.mjs CHANGED
@@ -31,6 +31,7 @@ Targeting & Scope:
31
31
 
32
32
  Audit Intelligence:
33
33
  --target <text> Compliance target label (default: "WCAG 2.2 AA").
34
+ --axe-tags <csv> Comma-separated axe tags (e.g., wcag2a,wcag2aa).
34
35
  --only-rule <id> Only check for this specific rule ID.
35
36
  --ignore-findings <csv> Ignore specific rule IDs.
36
37
  --exclude-selectors <csv> Exclude CSS selectors from scan.
@@ -136,6 +137,7 @@ async function main() {
136
137
  const routes = getArgValue("routes");
137
138
  const waitMs = getArgValue("wait-ms") || DEFAULTS.waitMs;
138
139
  const timeoutMs = getArgValue("timeout-ms") || DEFAULTS.timeoutMs;
140
+ const axeTags = getArgValue("axe-tags");
139
141
 
140
142
  const sessionFile = getInternalPath("a11y-session.json");
141
143
  let projectDir = getArgValue("project-dir");
@@ -254,6 +256,7 @@ async function main() {
254
256
  if (viewport) {
255
257
  scanArgs.push("--viewport", `${viewport.width}x${viewport.height}`);
256
258
  }
259
+ if (axeTags) scanArgs.push("--axe-tags", axeTags);
257
260
 
258
261
  await runScript("engine/dom-scanner.mjs", scanArgs, childEnv);
259
262
 
@@ -34,6 +34,10 @@ export const ASSET_PATHS = {
34
34
  ),
35
35
  codePatterns: path.join(ASSET_ROOT, "remediation", "code-patterns.json"),
36
36
  },
37
+ engine: {
38
+ cdpChecks: path.join(ASSET_ROOT, "engine", "cdp-checks.json"),
39
+ pa11yConfig: path.join(ASSET_ROOT, "engine", "pa11y-config.json"),
40
+ },
37
41
  reporting: {
38
42
  wcagReference: path.join(ASSET_ROOT, "reporting", "wcag-reference.json"),
39
43
  complianceConfig: path.join(
@@ -745,7 +745,12 @@ function computeTestingMethodology(payload) {
745
745
  const scanned = routes.filter((r) => !r.error).length;
746
746
  const errored = routes.filter((r) => r.error).length;
747
747
  return {
748
- automated_tools: ["axe-core (via @axe-core/playwright)", "Playwright + Chromium"],
748
+ automated_tools: [
749
+ "axe-core (via @axe-core/playwright)",
750
+ "CDP accessibility tree checks (Playwright)",
751
+ "pa11y (HTML CodeSniffer via Puppeteer)",
752
+ "Playwright + Chromium",
753
+ ],
749
754
  compliance_target: "WCAG 2.2 AA",
750
755
  pages_scanned: scanned,
751
756
  pages_errored: errored,
@@ -826,6 +831,8 @@ function buildFindings(inputPayload, cliArgs) {
826
831
  findings.push({
827
832
  id: "",
828
833
  rule_id: v.id,
834
+ source_rule_id: v.source_rule_id || null,
835
+ source: v.source || "axe",
829
836
  title: v.help,
830
837
  severity: IMPACT_MAP[v.impact] || "Medium",
831
838
  wcag: mapWcag(v.tags),