@diegovelasquezweb/a11y-engine 0.7.4 → 0.7.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegovelasquezweb/a11y-engine",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "WCAG 2.2 accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @file enrich.mjs
4
+ * @description CLI script that reads a11y-findings.json, enriches Critical/Serious
5
+ * findings using the Claude AI module, and writes the result back.
6
+ * Runs as a child process from audit.mjs after the analyzer step.
7
+ */
8
+
9
+ import { fileURLToPath } from "node:url";
10
+ import { log, getInternalPath, writeJson } from "../core/utils.mjs";
11
+ import { enrichWithAI } from "./claude.mjs";
12
+
13
+ async function main() {
14
+ const apiKey = process.env.ANTHROPIC_API_KEY;
15
+ if (!apiKey) {
16
+ log.warn("No ANTHROPIC_API_KEY found — skipping AI enrichment.");
17
+ process.exit(0);
18
+ }
19
+
20
+ const findingsPath = getInternalPath("a11y-findings.json");
21
+
22
+ let payload;
23
+ try {
24
+ const { readFileSync } = await import("node:fs");
25
+ payload = JSON.parse(readFileSync(findingsPath, "utf-8"));
26
+ } catch (err) {
27
+ log.warn(`Could not read findings file — skipping AI enrichment: ${err.message}`);
28
+ process.exit(0);
29
+ }
30
+
31
+ const findings = payload.findings ?? [];
32
+ if (findings.length === 0) {
33
+ log.info("No findings to enrich.");
34
+ process.exit(0);
35
+ }
36
+
37
+ const stack = payload.metadata?.projectContext ?? {};
38
+ const repoUrl = process.env.A11Y_REPO_URL || payload.metadata?.repoUrl || null;
39
+ const githubToken = process.env.GH_TOKEN || undefined;
40
+
41
+ log.info(`AI enrichment: processing up to 20 Critical/Serious findings...`);
42
+
43
+ const enriched = await enrichWithAI(findings, { stack, repoUrl }, {
44
+ enabled: true,
45
+ apiKey,
46
+ githubToken,
47
+ });
48
+
49
+ const enrichedWithFlag = enriched.map((f, i) => {
50
+ const original = findings[i];
51
+ const wasImproved = original && (
52
+ f.fixDescription !== original.fixDescription ||
53
+ f.fixCode !== original.fixCode
54
+ );
55
+ return wasImproved ? { ...f, aiEnhanced: true } : f;
56
+ });
57
+
58
+ writeJson(findingsPath, { ...payload, findings: enrichedWithFlag });
59
+
60
+ const improved = enrichedWithFlag.filter((f) => f.aiEnhanced).length;
61
+ log.success(`AI enrichment complete. ${improved} finding(s) improved.`);
62
+ }
63
+
64
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
65
+ main().catch((err) => {
66
+ log.warn(`AI enrichment failed (non-fatal): ${err.message}`);
67
+ process.exit(0); // non-fatal — never block the pipeline
68
+ });
69
+ }
package/src/cli/audit.mjs CHANGED
@@ -294,6 +294,14 @@ async function main() {
294
294
  if (resolvedFramework) analyzerArgs.push("--framework", resolvedFramework);
295
295
  await runScript("../enrichment/analyzer.mjs", analyzerArgs);
296
296
 
297
+ if (process.env.ANTHROPIC_API_KEY) {
298
+ await runScript("../ai/enrich.mjs", [], {
299
+ ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
300
+ ...(repoUrl ? { A11Y_REPO_URL: repoUrl } : {}),
301
+ ...(githubToken ? { GH_TOKEN: githubToken } : {}),
302
+ });
303
+ }
304
+
297
305
  if ((projectDir || repoUrl) && !skipPatterns) {
298
306
  const patternArgs = [];
299
307
  if (projectDir) {