@diegovelasquezweb/a11y-engine 0.11.35 → 0.11.37

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.11.35",
3
+ "version": "0.11.37",
4
4
  "description": "WCAG 2.2 accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -385,7 +385,28 @@ function parseJsonBlock(text) {
385
385
  }
386
386
  }
387
387
 
388
- async function callClaudeForPatch({ apiKey, model, aiInput }) {
388
+ function extractRemediationContext(remediationPath) {
389
+ if (!remediationPath || !fs.existsSync(remediationPath)) return null;
390
+ try {
391
+ const content = fs.readFileSync(remediationPath, "utf8");
392
+ const sections = [];
393
+ const guardrailsMatch = content.match(/## Agent Operating Procedures \(Guardrails\)([\s\S]*?)(?=\n---|\n##|$)/);
394
+ if (guardrailsMatch) {
395
+ sections.push("## Project Guardrails (from audit)\n" + guardrailsMatch[1].trim());
396
+ }
397
+ const sourceMatch = content.match(/## Source File Locations([\s\S]*?)(?=\n---|\n##|$)/);
398
+ if (sourceMatch) {
399
+ sections.push("## Source File Locations (from audit)\n" + sourceMatch[1].trim());
400
+ }
401
+ return sections.length > 0 ? sections.join("\n\n") : null;
402
+ } catch {
403
+ return null;
404
+ }
405
+ }
406
+
407
+ async function callClaudeForPatch({ apiKey, model, aiInput, remediationPath }) {
408
+ const remediationContext = extractRemediationContext(remediationPath);
409
+
389
410
  const system = [
390
411
  "You are an accessibility fix engine.",
391
412
  "Return JSON only — no markdown fences, no extra text.",
@@ -394,9 +415,10 @@ async function callClaudeForPatch({ apiKey, model, aiInput }) {
394
415
  "Generate text-replacement changes in the provided source files.",
395
416
  "CRITICAL — filePath rules: use the EXACT filePath string from the files array. Never derive filePath from area, url, selector, or any other field. Never add or remove leading slashes or file extensions.",
396
417
  "CRITICAL — search accuracy: the 'search' value must be a verbatim copy of a substring from the file content. Do not paraphrase, reformat, or reconstruct it — copy it character-for-character.",
397
- "For PAT findings: finding.matchLine contains the EXACT content of the line to fix — use it as your primary search anchor. finding.surroundingLines gives the wider context if you need a multi-line anchor.",
398
418
  "For insertions (new element not yet in the file), anchor the search on the nearest existing surrounding element and include it in both search and replace.",
399
419
  "Do not create new files. Only write changes for filePaths listed in the files array.",
420
+ "CSS files are never in the files array. Fix visual issues (touch targets, sizing) using inline style attributes or markup changes in the HTML file — never reference or create .css files.",
421
+ ...(remediationContext ? ["", "## Project Context (from audit report)", remediationContext] : []),
400
422
  "Schema:",
401
423
  "{\"changes\":[{\"filePath\":\"...\",\"search\":\"...\",\"replace\":\"...\"}],\"verifyRule\":\"...\",\"verifyRoute\":\"...\",\"notes\":\"...\"}",
402
424
  ].join("\n");
@@ -521,6 +543,7 @@ export async function applyFindingFix(input) {
521
543
  const findingId = typeof input.findingId === "string" ? input.findingId.trim() : "";
522
544
  const projectDir = typeof input.projectDir === "string" ? input.projectDir.trim() : "";
523
545
  const projectHints = typeof input.projectHints === "string" ? input.projectHints.trim() : "";
546
+ const remediationPath = typeof input.remediationPath === "string" ? input.remediationPath.trim() : (process.env.REMEDIATION_PATH || "");
524
547
 
525
548
  if (!findingId || !projectDir) {
526
549
  return buildResult({
@@ -580,7 +603,7 @@ export async function applyFindingFix(input) {
580
603
  let claudeUsage = { input_tokens: 0, output_tokens: 0 };
581
604
  if (apiKey) {
582
605
  try {
583
- const { patch, usage } = await callClaudeForPatch({ apiKey, model, aiInput });
606
+ const { patch, usage } = await callClaudeForPatch({ apiKey, model, aiInput, remediationPath });
584
607
  patchOutput = patch;
585
608
  claudeUsage = usage;
586
609
  } catch {
@@ -781,6 +804,7 @@ export async function applyFindingsFix(input) {
781
804
  : [];
782
805
  const projectDir = typeof input.projectDir === "string" ? input.projectDir.trim() : "";
783
806
  const projectHints = typeof input.projectHints === "string" ? input.projectHints.trim() : "";
807
+ const remediationPath = typeof input.remediationPath === "string" ? input.remediationPath.trim() : (process.env.REMEDIATION_PATH || "");
784
808
  const apiKey = input.ai?.apiKey || process.env.ANTHROPIC_API_KEY || "";
785
809
  const model = input.ai?.model || DEFAULT_MODEL;
786
810
 
@@ -889,7 +913,7 @@ export async function applyFindingsFix(input) {
889
913
  let claudeUsage = { input_tokens: 0, output_tokens: 0 };
890
914
  if (apiKey) {
891
915
  try {
892
- const { patch, usage } = await callClaudeForPatch({ apiKey, model, aiInput });
916
+ const { patch, usage } = await callClaudeForPatch({ apiKey, model, aiInput, remediationPath });
893
917
  patchOutput = patch;
894
918
  claudeUsage = usage;
895
919
  } catch {