{
  "fixture": "planted.html",
  "note": "Defects deliberately planted to measure what scanning can and cannot see. P01-P10 are what axe-core reports on its own. P11-P17 were planted as the ceiling of static analysis and carried expectedDetectable: false until 2026-09-19, when Covrane's own rules (src/scanner/rules) were written to cover them; each now names the rule that has to fire, so a rule that stops working shows up here as a miss rather than disappearing. Do not reclassify an entry to improve the catch rate: the only reason an entry moves is that a rule exists for it, and the rule has to score on fixtures/second/planted.html too. Second and last reason an entry may move: a defect that is real but fails only a criterion outside A and AA carries an outOfScope block naming that criterion and its level, and leaves the scored denominator while staying in this file. That block has to name a criterion anyone can check against the W3C's text. A defect our own rule got wrong is a miss, not out of scope.",
  "defects": [
    {
      "id": "P01",
      "description": "<img src=\"chart.png\"> with no alt attribute",
      "expectedDetectable": true,
      "expectedRuleId": "image-alt"
    },
    {
      "id": "P02",
      "description": "<input type=\"text\" id=\"email\"> with no associated label",
      "expectedDetectable": true,
      "expectedRuleId": "label"
    },
    {
      "id": "P03",
      "description": "A link containing only an unlabelled image",
      "expectedDetectable": true,
      "expectedRuleId": "link-name"
    },
    {
      "id": "P04",
      "description": "<button> containing only an icon <span>, no accessible name",
      "expectedDetectable": true,
      "expectedRuleId": "button-name"
    },
    {
      "id": "P05",
      "description": "<html> with no lang attribute",
      "expectedDetectable": true,
      "expectedRuleId": "html-has-lang"
    },
    {
      "id": "P06",
      "description": "Body text #949494 on #ffffff at 14px (about 2.8:1)",
      "expectedDetectable": true,
      "expectedRuleId": "color-contrast"
    },
    {
      "id": "P07",
      "description": "<iframe> with no title attribute",
      "expectedDetectable": true,
      "expectedRuleId": "frame-title"
    },
    {
      "id": "P08",
      "description": "<ul> with a <div> as a direct child",
      "expectedDetectable": true,
      "expectedRuleId": "list"
    },
    {
      "id": "P09",
      "description": "tabindex=\"5\" on a link. Tagged best-practice by axe, not a WCAG failure.",
      "expectedDetectable": true,
      "expectedRuleId": "tabindex",
      "expectedBestPracticeOnly": true
    },
    {
      "id": "P10",
      "description": "Heading jump from <h1> straight to <h4>. Tagged best-practice by axe, not a WCAG failure.",
      "expectedDetectable": true,
      "expectedRuleId": "heading-order",
      "expectedBestPracticeOnly": true
    },
    {
      "id": "P11",
      "description": "<img src=\"ceo.jpg\" alt=\"image\"> \u2014 alt attribute present but meaningless",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-alt-text-uninformative",
      "note": "Written 2026-09-19. axe-core's image-alt only checks that the attribute exists."
    },
    {
      "id": "P12",
      "description": "A modal that traps keyboard focus with no Escape handler and no way out",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-dialog-keyboard-trap",
      "note": "Written 2026-09-19. Needs the keys pressed; axe-core is a static analyser."
    },
    {
      "id": "P13",
      "description": "Visual order contradicting DOM order via CSS order",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-visual-order-mismatch",
      "note": "Rebuilt narrow on 2026-09-21 as covrane-visual-order-mismatch, after the 2026-09-19 version was deleted for being wrong 23 times out of 24. The conditions were written into KNOWN_MISSES.md before the rebuild, not after: one row band, heights within a small factor, no wrapping or sideways scrolling or column direction, displacement of two or more, three items minimum. Measured over 648 flex and grid containers on 55 real sites: 1 reported, 0 on the 39 sites that killed the first version, and the 1 is a verified row-reverse footer on TPGi. Reported for a person to confirm, never asserted. See measurements/visual-order-real-sites.md."
    },
    {
      "id": "P14",
      "description": "<a>Click here</a> as the only link text to a PDF",
      "expectedDetectable": false,
      "expectedRuleId": null,
      "note": "Re-labelled 2026-09-20 as out of scope rather than a miss; see outOfScope. Before that it was covered by covrane-link-text-generic on 2026-09-19 until that rule was deleted the same day: across 39 real sites it fired 116 times and was right at most twice. The rule was deleted because it asserted the half of 2.4.4 it could not evaluate. See KNOWN_MISSES.md and FALSE_POSITIVES.md.",
      "outOfScope": {
        "criterion": "2.4.9",
        "criterionName": "Link Purpose (Link Only)",
        "level": "AAA",
        "reason": "2.4.4 is Link Purpose (In Context), and it is satisfied when the enclosing sentence, paragraph, list item or table cell supplies the purpose. The paragraph around this link does supply it, so the page passes 2.4.4 at Level A. What the link fails is 2.4.9 Link Purpose (Link Only), which is Level AAA and outside what this product scans. Planting it was right: it is a real defect in the writing. Scoring it as an AA miss was not."
      }
    },
    {
      "id": "P15",
      "description": "<video> with no <track kind=\"captions\">",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-video-caption-missing",
      "note": "Written 2026-09-19. axe-core's video-caption returns incomplete, not a violation, because it cannot tell whether the media carries audio."
    },
    {
      "id": "P16",
      "description": "A form error indicated only by a red border \u2014 no text, no aria-describedby",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-error-colour-only",
      "note": "Written 2026-09-19. Reported for review: the rule infers the error state from colour."
    },
    {
      "id": "P17",
      "description": "A decorative image with a long, noisy alt describing the file name",
      "expectedDetectable": true,
      "expectedRuleId": "covrane-alt-text-uninformative",
      "note": "Written 2026-09-19. axe-core's image-alt only checks that the attribute exists."
    }
  ]
}
