Fix Accessibility Plan Executor
Prerequisites
.navable-plan.json must exist in the project root
- If no plan exists, tell the user to run the
scan-accessibility skill first
Workflow
Step 1: Load Plan
- Read
.navable-plan.json from the project root
- Parse and display a summary:
- Total items, pending count, done count, skipped count
- Breakdown by impact level
- List pending items in their current order (already sorted by priority)
Step 2: Determine Scope
- If the user specified an item ID (e.g. "fix-3") → fix only that item
- If the user said "all" or didn't specify → fix all pending items in order
- If the user asked about a specific rule (e.g. "fix the contrast issues") → filter items by
ruleId
Step 3: Fix Each Item
Before starting: Group plan items by DOM element. Multiple items often target the same element
(separate axe nodes in a multi-node violation, or cross-engine flags under different WCAG criteria).
Fixing one element once avoids regressions and cuts file reads/writes.
Two items belong in the same bucket when both:
- Selectors match — identical, or one selector is a tail of the other (the longer one has
> immediately before where the shorter one starts; the shorter side need not contain >
itself, so img:nth-child(1) matches … > img:nth-child(1)), or they match after
stripping [attribute] filters (e.g. button[type="button"] matches button). When you fall
back to the attribute-stripped path, require exact HTML equality — distinct elements like
input[type="checkbox"] and input[type="radio"] collapse to the same stripped selector, so
any HTML divergence means they are different elements.
affectedNodes[0].html snippets match — normalize whitespace (collapse runs of spaces,
trim) and lowercase, then compare the first ~200 characters. The 200-char window is wide enough
to catch divergence in child content (e.g. <option> text inside two different <select>).
If selectors look similar but HTML differs, treat as different elements. Two <select> in two
forms can share the suffix form > div:nth-child(4) > select — their <option> content
disambiguates them, but only if you compare enough of the HTML.
:nth-child index drift. axe and HTMLCS occasionally disagree on :nth-child indices when
there are sibling text nodes or comments. If two findings are clearly the same element but the
indices differ by one, trust the HTML snippet over the selector and bucket them together.
For each bucket, design one minimal edit addressing every fix in the bucket, then call
update_fix_status with all resolved fix IDs in one call.
For each pending item (or bucket):
- Set status to
in_progress in .navable-plan.json and save
- Identify the violation category from
item.ruleId
- Load the fix guide — use the category mapping from the
scan-accessibility skill:
- Images:
scan-accessibility/references/fix-guide-images.md
- Forms:
scan-accessibility/references/fix-guide-forms.md
- Color:
scan-accessibility/references/fix-guide-color.md
- Navigation:
scan-accessibility/references/fix-guide-navigation.md
- Headings:
scan-accessibility/references/fix-guide-headings.md
- Landmarks:
scan-accessibility/references/fix-guide-landmarks.md
- ARIA:
scan-accessibility/references/fix-guide-aria.md
- Keyboard:
scan-accessibility/references/fix-guide-keyboard.md
- Language:
scan-accessibility/references/fix-guide-language.md
- Tables:
scan-accessibility/references/fix-guide-tables.md
- Locate the source file using
item.affectedNodes:
- Use CSS selectors and HTML snippets to find the component
- Search for unique class names, text content, or attributes in the codebase
- Check
package.json for framework (React/Vue/Svelte/Angular) to guide file search
- Apply the fix following the before/after pattern from the fix guide
- Update
.navable-plan.json:{ "status": "done", "appliedAt": "2025-01-15T10:30:00.000Z" }
- Save
.navable-plan.json after each fix (not in a batch)
Step 4: Summary
After fixing all targeted items:
- Report what was fixed (count, rule IDs, impact levels)
- If all items are done → suggest re-scanning with
run_accessibility_scan for verification
- If items remain → list what's still pending with their priority
Step 5: Verification (if all items done)
If the user agrees to verify:
- Call
run_accessibility_scan with the same URL from plan.url
- Compare results against the plan
- Update
.navable-plan.json:{
"verification": {
"completedAt": "2025-01-15T11:00:00.000Z",
"remainingViolations": 0,
"passed": true
}
}
Status Values
| Status |
Meaning |
pending |
Not yet addressed |
in_progress |
Currently being fixed (set at start of fix) |
done |
Fix applied successfully |
skipped |
Intentionally skipped — add a comment explaining why |
Skipping Items
If an item cannot be fixed (e.g. third-party content, intentional design decision):
- Set
status: "skipped" in .navable-plan.json
- Explain to the user why it was skipped
- Note: Critical items should not be skipped without explicit user confirmation
Gotchas
- Always save
.navable-plan.json after each individual fix. This ensures resumability if the
session is interrupted.
- Do not modify the
priority or sort order of items. The server set the correct order.
- If a source file can't be found, report the CSS selector and HTML snippet to the user and ask
for guidance.
- Multiple items may affect the same file. Apply fixes carefully to avoid conflicts. Re-read the
file before each fix.
- The
manualReview array contains issues that need human judgment. Mention these to the user
but do not auto-fix.
1---2name: fix-accessibility3description: Executes an existing accessibility fix plan from .navable-plan.json. Works through pending items in priority order, applying code fixes with before/after patterns. Use when a .navable-plan.json file exists and the user wants to fix, apply, or continue fixing accessibility issues.4license: MIT5---67# Fix Accessibility Plan Executor89## Prerequisites1011- `.navable-plan.json` must exist in the project root12- If no plan exists, tell the user to run the `scan-accessibility` skill first1314## Workflow1516### Step 1: Load Plan17181. Read `.navable-plan.json` from the project root192. Parse and display a summary:20 - Total items, pending count, done count, skipped count21 - Breakdown by impact level223. List pending items in their current order (already sorted by priority)2324### Step 2: Determine Scope2526- If the user specified an item ID (e.g. "fix-3") → fix only that item27- If the user said "all" or didn't specify → fix all pending items in order28- If the user asked about a specific rule (e.g. "fix the contrast issues") → filter items by29 `ruleId`3031### Step 3: Fix Each Item3233**Before starting:** Group plan items by DOM element. Multiple items often target the same element34(separate axe nodes in a multi-node violation, or cross-engine flags under different WCAG criteria).35Fixing one element once avoids regressions and cuts file reads/writes.3637Two items belong in the same bucket when both:38391. **Selectors match** — identical, **or** one selector is a tail of the other (the longer one has40 ` > ` immediately before where the shorter one starts; the shorter side need not contain ` > `41 itself, so `img:nth-child(1)` matches `… > img:nth-child(1)`), **or** they match after42 stripping `[attribute]` filters (e.g. `button[type="button"]` matches `button`). When you fall43 back to the attribute-stripped path, require **exact HTML equality** — distinct elements like44 `input[type="checkbox"]` and `input[type="radio"]` collapse to the same stripped selector, so45 any HTML divergence means they are different elements.462. **`affectedNodes[0].html` snippets match** — normalize whitespace (collapse runs of spaces,47 trim) and lowercase, then compare the first ~200 characters. The 200-char window is wide enough48 to catch divergence in child content (e.g. `<option>` text inside two different `<select>`).4950> If selectors look similar but HTML differs, treat as different elements. Two `<select>` in two51> forms can share the suffix `form > div:nth-child(4) > select` — their `<option>` content52> disambiguates them, but only if you compare enough of the HTML.53>54> **`:nth-child` index drift.** axe and HTMLCS occasionally disagree on `:nth-child` indices when55> there are sibling text nodes or comments. If two findings are clearly the same element but the56> indices differ by one, trust the HTML snippet over the selector and bucket them together.5758For each bucket, design **one minimal edit** addressing every fix in the bucket, then call59`update_fix_status` with **all** resolved fix IDs in one call.6061For each pending item (or bucket):62631. **Set status to `in_progress`** in `.navable-plan.json` and save642. **Identify the violation category** from `item.ruleId`653. **Load the fix guide** — use the category mapping from the `scan-accessibility` skill:66 - Images: `scan-accessibility/references/fix-guide-images.md`67 - Forms: `scan-accessibility/references/fix-guide-forms.md`68 - Color: `scan-accessibility/references/fix-guide-color.md`69 - Navigation: `scan-accessibility/references/fix-guide-navigation.md`70 - Headings: `scan-accessibility/references/fix-guide-headings.md`71 - Landmarks: `scan-accessibility/references/fix-guide-landmarks.md`72 - ARIA: `scan-accessibility/references/fix-guide-aria.md`73 - Keyboard: `scan-accessibility/references/fix-guide-keyboard.md`74 - Language: `scan-accessibility/references/fix-guide-language.md`75 - Tables: `scan-accessibility/references/fix-guide-tables.md`764. **Locate the source file** using `item.affectedNodes`:77 - Use CSS selectors and HTML snippets to find the component78 - Search for unique class names, text content, or attributes in the codebase79 - Check `package.json` for framework (React/Vue/Svelte/Angular) to guide file search805. **Apply the fix** following the before/after pattern from the fix guide816. **Update `.navable-plan.json`**:82 ```json83 { "status": "done", "appliedAt": "2025-01-15T10:30:00.000Z" }84 ```857. **Save `.navable-plan.json` after each fix** (not in a batch)8687### Step 4: Summary8889After fixing all targeted items:90911. Report what was fixed (count, rule IDs, impact levels)922. If all items are done → suggest re-scanning with `run_accessibility_scan` for verification933. If items remain → list what's still pending with their priority9495### Step 5: Verification (if all items done)9697If the user agrees to verify:98991. Call `run_accessibility_scan` with the same URL from `plan.url`1002. Compare results against the plan1013. Update `.navable-plan.json`:102 ```json103 {104 "verification": {105 "completedAt": "2025-01-15T11:00:00.000Z",106 "remainingViolations": 0,107 "passed": true108 }109 }110 ```111112## Status Values113114| Status | Meaning |115| ------------- | ---------------------------------------------------- |116| `pending` | Not yet addressed |117| `in_progress` | Currently being fixed (set at start of fix) |118| `done` | Fix applied successfully |119| `skipped` | Intentionally skipped — add a comment explaining why |120121## Skipping Items122123If an item cannot be fixed (e.g. third-party content, intentional design decision):1241251. Set `status: "skipped"` in `.navable-plan.json`1262. Explain to the user why it was skipped1273. Note: Critical items should not be skipped without explicit user confirmation128129## Gotchas130131- **Always save `.navable-plan.json` after each individual fix.** This ensures resumability if the132 session is interrupted.133- **Do not modify the `priority` or sort order of items.** The server set the correct order.134- **If a source file can't be found**, report the CSS selector and HTML snippet to the user and ask135 for guidance.136- **Multiple items may affect the same file.** Apply fixes carefully to avoid conflicts. Re-read the137 file before each fix.138- **The `manualReview` array** contains issues that need human judgment. Mention these to the user139 but do not auto-fix.