@diegovelasquezweb/a11y-engine 0.11.51 → 0.11.52

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.51",
3
+ "version": "0.11.52",
4
4
  "description": "WCAG 2.2 accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -696,19 +696,36 @@ export async function applyFindingFix(input) {
696
696
 
697
697
  const validation = validateAiPatchOutput(patchOutput, projectDir, candidateSet);
698
698
  if (!validation.ok) {
699
- // When Claude returns no changes, it may be because a prior fix (e.g. the DOM
700
- // batch) already resolved this issue. Verify by checking if the pattern's
701
- // context_reject_regex now matches the surroundingLines of the target element.
699
+ // When Claude returns no changes OR a no-op patch (search===replace), it may be
700
+ // because a prior fix (e.g. the DOM batch) already resolved this issue.
701
+ // Verify by checking if the pattern's context_reject_regex now matches the
702
+ // current file content around the target element.
702
703
  // If it does, the element is already accessible — count as resolved.
703
- if (validation.reason === "AI patch output has no changes") {
704
+ const isNoChanges = validation.reason === "AI patch output has no changes";
705
+ const isNoop = validation.reason.startsWith("AI generated a no-op patch for ");
706
+ if (isNoChanges || isNoop) {
704
707
  const patternId = finding.pattern_id || finding.patternId || "";
705
708
  const patternDef = (ASSETS.remediation.codePatterns?.patterns || [])
706
709
  .find((p) => p.id === patternId);
707
710
  const rejectRegex = patternDef?.context_reject_regex;
708
711
  if (rejectRegex) {
709
- const context = [aiInput.finding.surroundingLines, aiInput.finding.matchLine]
710
- .filter(Boolean)
711
- .join("\n");
712
+ // For no-op patches, read the CURRENT file content — the DOM batch may have
713
+ // already resolved this finding by modifying the file after the scan.
714
+ let context;
715
+ if (isNoop) {
716
+ try {
717
+ const currentContent = fs.readFileSync(candidate.abs, "utf8");
718
+ const fileLines = currentContent.split("\n");
719
+ const lineIdx = Math.max(0, (aiInput.finding.line || 1) - 1);
720
+ const start = Math.max(0, lineIdx - 4);
721
+ const end = Math.min(fileLines.length, lineIdx + 5);
722
+ context = fileLines.slice(start, end).join("\n");
723
+ } catch {
724
+ context = [aiInput.finding.surroundingLines, aiInput.finding.matchLine].filter(Boolean).join("\n");
725
+ }
726
+ } else {
727
+ context = [aiInput.finding.surroundingLines, aiInput.finding.matchLine].filter(Boolean).join("\n");
728
+ }
712
729
  try {
713
730
  if (new RegExp(rejectRegex, "i").test(context)) {
714
731
  return buildResult({