feat: Add GitHub Copilot support, document scanning, 19 agents, and comprehensive docs#3
Conversation
There was a problem hiding this comment.
Pull request overview
Expands the repository’s accessibility “agent team” to support GitHub Copilot and adds CI-oriented accessibility tooling, including new document (Office/PDF) scanning scripts and an intentionally broken example project for demos/training.
Changes:
- Add new CI scripts for markup a11y linting plus Office/PDF accessibility scanning.
- Expand Copilot and Claude agent catalogs (new agents + updated guidance, including link-checker and accessibility-wizard).
- Add an
example/project intended to contain common accessibility failures for testing/training.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| example/styles.css | Adds intentionally failing CSS patterns for a11y tooling demos. |
| example/index.html | Adds intentionally failing HTML patterns for a11y tooling demos. |
| example/README.md | Documents how to use the intentionally broken example with agents/tools. |
| desktop-extension/manifest.json | Updates tool/keyword metadata to include new scanning capabilities. |
| .vscode/tasks.json | Adds a VS Code task to run axe-core scans against a user-provided URL. |
| .github/workflows/a11y-check.yml | Updates PR-time accessibility checks to use the new Node-based linter and axe CLI. |
| .github/scripts/a11y-lint.mjs | Introduces a dependency-free markup/CSS a11y linter for CI. |
| .github/scripts/office-a11y-scan.mjs | Introduces Office document scanning and SARIF output for CI/code scanning. |
| .github/scripts/pdf-a11y-scan.mjs | Introduces PDF scanning and SARIF output for CI/code scanning. |
| .github/copilot-review-instructions.md | Extends PR review guidance (notably link checks). |
| .github/copilot-instructions.md | Updates Copilot workspace guidance with new agents (link-checker, accessibility-wizard). |
| .github/agents/accessibility-lead.md | Updates “lead” agent’s delegation matrix and link-related standards. |
| .github/agents/accessibility-wizard.md | Adds a guided audit agent intended to orchestrate a full multi-phase review. |
| .github/agents/contrast-master.md | Extends visual/contrast guidance (prefers-* / forced-colors coverage). |
| .github/agents/excel-accessibility.md | Adds Excel accessibility specialist agent content. |
| .github/agents/link-checker.md | Adds link text/purpose specialist agent content. |
| .github/agents/office-scan-config.md | Adds Office scan configuration agent content. |
| .github/agents/pdf-accessibility.md | Adds PDF accessibility specialist agent content. |
| .github/agents/pdf-scan-config.md | Adds PDF scan configuration agent content. |
| .github/agents/powerpoint-accessibility.md | Adds PowerPoint accessibility specialist agent content. |
| .github/agents/tables-data-specialist.md | Minor update to table-sort icon example. |
| .github/agents/testing-coach.md | Adds axe-core integration guidance for the testing coach. |
| .github/agents/word-accessibility.md | Adds Word accessibility specialist agent content. |
| .claude/hooks/a11y-team-eval.sh | Updates Claude hook guidance to include link-checker + accessibility-wizard. |
| .claude/hooks/a11y-team-eval.ps1 | Updates Claude hook guidance to include link-checker + accessibility-wizard. |
| .claude/agents/accessibility-lead.md | Mirrors lead-agent updates for Claude. |
| .claude/agents/accessibility-wizard.md | Mirrors guided audit agent content for Claude. |
| .claude/agents/contrast-master.md | Mirrors contrast/prefers-* updates for Claude. |
| .claude/agents/excel-accessibility.md | Mirrors Excel agent content for Claude. |
| .claude/agents/link-checker.md | Mirrors link-checker agent content for Claude. |
| .claude/agents/office-scan-config.md | Mirrors Office scan config agent content for Claude. |
| .claude/agents/pdf-accessibility.md | Mirrors PDF accessibility agent content for Claude. |
| .claude/agents/pdf-scan-config.md | Mirrors PDF scan config agent content for Claude. |
| .claude/agents/powerpoint-accessibility.md | Mirrors PowerPoint agent content for Claude. |
| .claude/agents/tables-data-specialist.md | Mirrors table-sort icon example change for Claude. |
| .claude/agents/testing-coach.md | Mirrors axe-core guidance updates for Claude. |
| .claude/agents/word-accessibility.md | Mirrors Word agent content for Claude. |
| @@ -0,0 +1,211 @@ | |||
| --- | |||
There was a problem hiding this comment.
This Copilot agent file’s YAML front matter is missing a name: field (most other files in .github/agents/ include both name and description). If Copilot relies on the name field for agent registration, this file may not load correctly. Consider adding name: pdf-accessibility to the front matter for consistency.
| --- | |
| --- | |
| name: pdf-accessibility |
| ## Expected Findings | ||
|
|
||
| When all issues are fixed, matching the patterns in `index-fixed.html`, the agents should report a clean audit. Use this as a learning tool — see how many issues you can identify before running the agents, then compare. |
There was a problem hiding this comment.
index-fixed.html is referenced here but there is no example/index-fixed.html in the repo. Either add that fixed reference file or update this text to point to the actual expected “fixed” artifact (or remove the reference).
| function add(id, sev, msg, loc) { | ||
| if (disabled.has(id) || !sevFilter.has(sev)) return; | ||
| findings.push({ ruleId: id, severity: sev, message: msg, location: loc || "document" }); | ||
| } | ||
| const titles = xmlText(core, "dc:title"); | ||
| if (!titles.length || !titles[0]) add("DOCX-E004", "error", "Document title is not set", "docProps/core.xml"); | ||
| if (!xmlHas(doc, "w:lang") && !xmlHas(core, "dc:language")) add("DOCX-T001", "tip", "Document language is not set", "word/settings.xml"); |
There was a problem hiding this comment.
DOCX-T001 claims to check for language in word/settings.xml, but the scan only reads word/document.xml and docProps/core.xml and never loads word/settings.xml. This will miss valid language settings and can produce false “language not set” findings. Consider loading word/settings.xml and checking <w:lang> there (and/or adjust the location/message to match what is actually being checked).
| function add(id, sev, msg, loc) { | |
| if (disabled.has(id) || !sevFilter.has(sev)) return; | |
| findings.push({ ruleId: id, severity: sev, message: msg, location: loc || "document" }); | |
| } | |
| const titles = xmlText(core, "dc:title"); | |
| if (!titles.length || !titles[0]) add("DOCX-E004", "error", "Document title is not set", "docProps/core.xml"); | |
| if (!xmlHas(doc, "w:lang") && !xmlHas(core, "dc:language")) add("DOCX-T001", "tip", "Document language is not set", "word/settings.xml"); | |
| const settings = getZipXml(buf, entries, "word/settings.xml"); | |
| function add(id, sev, msg, loc) { | |
| if (disabled.has(id) || !sevFilter.has(sev)) return; | |
| findings.push({ ruleId: id, severity: sev, message: msg, location: loc || "document" }); | |
| } | |
| const titles = xmlText(core, "dc:title"); | |
| if (!titles.length || !titles[0]) add("DOCX-E004", "error", "Document title is not set", "docProps/core.xml"); | |
| const hasLangInSettings = xmlHas(settings, "w:lang"); | |
| const hasLangInDoc = xmlHas(doc, "w:lang"); | |
| const hasLangInCore = xmlHas(core, "dc:language"); | |
| if (!hasLangInSettings && !hasLangInDoc && !hasLangInCore) { | |
| add("DOCX-T001", "tip", "Document language is not set", "word/settings.xml"); | |
| } |
| */ | ||
|
|
||
| import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"; | ||
| import { join, relative, extname, basename, dirname } from "node:path"; |
There was a problem hiding this comment.
basename and dirname are imported but never used in this script. Removing unused imports will avoid dead code and keep the file easier to maintain.
| import { join, relative, extname, basename, dirname } from "node:path"; | |
| import { join, relative, extname } from "node:path"; |
| HTML_FILES=$(find . -name '*.html' -not -path './node_modules/*' -not -path './.git/*' -not -path './dist/*' -not -path './build/*' | head -20) | ||
| if [ -n "$HTML_FILES" ]; then | ||
| npx @axe-core/cli --exit --rules wcag2a,wcag2aa --disable color-contrast $HTML_FILES 2>/dev/null || true | ||
| else |
There was a problem hiding this comment.
The axe-core invocation uses --rules wcag2a,wcag2aa, but elsewhere in this repo (e.g., the run_axe_scan tool and VS Code task) WCAG filters are passed via --tags. wcag2a/wcag2aa are tags rather than rule IDs, so this may not behave as intended. Consider switching to --tags wcag2a,wcag2aa,wcag21a,wcag21aa (or aligning with the arguments used in desktop-extension/server/index.js).
| - name: Run accessibility lint (Node.js) | ||
| run: node .github/scripts/a11y-lint.mjs . |
There was a problem hiding this comment.
The workflow runs node .github/scripts/a11y-lint.mjs ., which will lint the entire repo including example/ (added in this PR and explicitly contains intentional accessibility violations). Since the lint script exits non-zero on errors, this will cause the CI job to fail even though the example is meant to be broken. Consider excluding example/ (or adding an allowlist/ignore list) from this workflow invocation so CI only enforces a11y on real product code.
| ".next", | ||
| ".nuxt", | ||
| "coverage", | ||
| "vendor", |
There was a problem hiding this comment.
IGNORED_DIRS does not include example/, but this PR adds an intentionally inaccessible example/ page/styles. When the lint script is run on repo root (as in CI), it will report errors for the example and exit 1. Consider adding support for ignore patterns (e.g., example, docs, configurable via CLI/env) or explicitly adding example to IGNORED_DIRS to avoid failing CI on intentional fixtures.
| "vendor", | |
| "vendor", | |
| "example", |
| # Run axe-core scan | ||
| run_axe_scan on example/index.html | ||
| ``` |
There was a problem hiding this comment.
The README suggests running run_axe_scan on example/index.html, but the run_axe_scan tool in this repo scans a live URL (e.g., http://localhost:3000) rather than a file path. Update the example instructions to either (1) serve example/ via a local web server and scan that URL, or (2) clarify the accepted input for run_axe_scan.
| import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"; | ||
| import { join, relative, extname, basename, dirname } from "node:path"; | ||
|
|
There was a problem hiding this comment.
basename and dirname are imported but never used in this script. Removing unused imports will avoid dead code and keep the file easier to maintain.
| if (info.hasFigures && info.hasAltOnFigures === false) add("PDFUA.13.001", "error", "Figure elements without alt text", "structure tree"); | ||
| if (info.hasTables) add("PDFUA.19.001", "warning", "Tables detected — verify header cells are designated", "structure tree"); | ||
| if (info.hasForms) add("PDFUA.26.001", "warning", "Form fields detected — verify tooltips and tab order", "AcroForm"); |
There was a problem hiding this comment.
These findings use PDF/UA rule IDs (PDFUA.19.001, PDFUA.26.001) but the checks only detect that tables/forms exist and cannot actually verify header cells or tooltips/tab order. Using conformance rule IDs for “manual verification needed” cases is misleading and can create false positives/incorrect severity. Consider switching these to best-practice “needs review” rule IDs (e.g., PDFBP.* or a PDFQ.*/custom namespace) and reserving PDFUA.* IDs for checks you can deterministically validate.
|
Hey Jeff — merged your changes into main. Here's what happened and why we had to do it manually: Why we couldn't merge directlyAfter your first PR (#1), we made significant improvements to the install pipeline on main:
Your branch replaced install.sh with a simpler version that hardcoded 6 agents and removed all the Copilot/cross-platform support. A straight merge would have overwritten the pipeline. What we did
Going forwardWhen adding new agents, just drop them in Thanks for the massive expansion — the document scanning agents and accessibility-wizard are great additions. |
…and hook schema updates (#30) * feat: add CSV reporters, CI linting, EPUB agents, and ecosystem enhancements - Enhancement 1: Register EPUB agents in both AGENTS.md files with new EPUB team - Enhancement 2: Create 5 missing Claude agents (epub-scan-config, cognitive-accessibility, design-system-auditor, epub-accessibility, mobile-accessibility) - Enhancement 3: Wire CSV reporters into all 4 wizard agents (web + document, both platforms) - Enhancement 4: Add markdown-csv-reporter agents, export-markdown-csv prompt, and documentation - Enhancement 5: Add markdown-a11y-lint.mjs CI script and markdown-lint workflow job New files: 23 (agents, prompts, docs, CI script, skill) Modified files: 14 (AGENTS.md, wizards, instructions, workflow, docs) * fix: align rule IDs to canonical format agents and add gap analysis rules - Aligned DOCX/XLSX/PPTX rule tables in both CSV reporters (Copilot + Claude) to canonical format agent IDs - Fixed Warning weight from 3 to 5 in Copilot CSV reporter ROI calculation - Added 5 new rules from Microsoft Accessibility Checker gap analysis: - DOCX-E008 (document-access-restricted/IRM) - DOCX-E009 (content-controls-without-titles) - XLSX-E007 (red-negative-numbers) - XLSX-E008 (workbook-access-restricted/IRM) - PPTX-E007 (presentation-access-restricted/IRM) - Updated format agents (word/excel/powerpoint-accessibility) with new rules - Updated office-scan-config agents with new rules - All rule IDs now consistent across format agents, CSV reporters, help-url-reference, and accessibility-rules SKILL * fix: complete code review fixes (34/34 findings resolved) High severity (previously fixed): - H-01: Manifest-based uninstall (prevents deleting user files) - H-02: ReDoS-resistant bounded regex patterns - H-03: ZIP bomb protection (200MB limit) - H-04: ZIP64 archive detection Medium severity: - M-01: validateFilePath write-mode enforcement at all 9 call sites - M-02: cd exit guard in install.sh embedded updater - M-03: ExecutionPolicy Bypass changed to RemoteSigned - M-04: Multi-line HTML tag limitation documented in a11y-lint - M-05: BOM-aware YAML front matter detection in markdown lint - M-06: Expanded emoji regex to cover supplemental/flag sequences - M-07: Removed stale path reference (previously fixed) - M-08: git clone error handling in install.ps1 and install.sh - M-09: PDFQ.REPO.NO_SCANNED_ONLY guarded against duplicate with PDFBP.TEXT.EXTRACTABLE - M-10: Title regex escaped parens (previously fixed) Low severity: - L-01: PS 5.1-compatible null-coalescing in 4 hook scripts - L-02: Dead imports removed (previously fixed) - L-03: lstatSync + symlink skip in all 4 lint/scan scripts - L-04: Link regex handles nested elements in a11y-lint - L-05: XML regex parsing limitations documented - L-06: Array.isArray checks (previously fixed) - L-08: JSON-safe string escaping in a11y-team-eval.sh - L-09: Hex format hints on contrast task inputs - L-10: Removed unused documentPath input from tasks.json - L-11: cd exit guards in update.sh - L-12: Skipped (JSON does not support comments) Informational: - I-01: Zod semver range fixed to ^3.25.0 - I-02: WCAG 2.1 to 2.2 in manifest.json (3 locations) - I-03: WCAG 2.1 to 2.2 in index.js (5 locations) - I-04: Empty catch blocks annotated in lint scripts - I-05: Concurrent processing opportunity noted - I-06: message.split fallback for messages without periods (5 locations) - I-07: Intentional anti-pattern banners in example files - I-08: Shared code duplication documented between lint scripts * fix: update hook schema to hookSpecificOutput and increase timeouts - Flatten Claude settings.json hook structure (remove nested hooks array) - Add Windows-specific command paths to Claude hooks - Migrate hook scripts from stopReason/systemMessage to hookSpecificOutput pattern - Increase hook timeouts from 5-10s to 10-15s for reliability - Add hookEventName metadata to all hook JSON responses - Update cross-platform handoff documentation - Add audit sessions log * fix: address PR review findings (#1-#4) - #1: gitignore .github/audit/ and remove sessions.log from tracking - #2: restore PreToolUse matcher (Bash|mcp_github) to scope safety gate - #3: migrate install.sh, install.ps1, uninstall.sh to flat hook schema - #4: annotate WCAG 2.4.13 Focus Appearance as (AAA) in CLAUDE.md and copilot-instructions.md * feat: add multi-agent reliability engineering and remove hooks Apply principles from GitHub blog article on multi-agent workflow reliability across the entire agent ecosystem. ## Hook Removal - Delete all hook files (.claude/hooks/, .github/hooks/) - Remove hook references from 60+ documentation files - Clean .claude/settings.json - Remove hook setup from install/uninstall/update scripts ## Multi-Agent Reliability - Create multi-agent-reliability.instructions.md - Add reliability standards to both AGENTS.md manifests - Add structured output contracts to 12 orchestrator files - Add output contracts + handoff transparency to 26 sub-agent files - Add handoff transparency sections to 21 custom prompt files ## Instruction Strengthening - Add Context Discovery, Audit Report Quality Requirements, and Automatic Trigger Detection to CLAUDE.md and copilot-instructions.md - Replace SESSION CONTEXT references with workspace context ## CI Fixes - Fix a11y-lint.mjs and markdown-a11y-lint.mjs for CI workflow All linters pass with 0 errors. * fix: add missing YAML front matter to skill files Ran skills and got errors - four SKILL.md files were missing YAML front matter (name + description). Added front matter to: - cognitive-accessibility/SKILL.md - design-system/SKILL.md - markdown-accessibility/SKILL.md - mobile-accessibility/SKILL.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add one-liner uninstall to README Mirrors the one-liner install section with curl/irm equivalents for uninstall on macOS/Linux and Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: taylorarndt <taylor@techopolis.online> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat: Full Accessibility Agent Team Expansion
Summary
This PR expands the A11y Agent Team from 5 original Claude Code agents to a comprehensive 19-agent ecosystem with full GitHub Copilot support, document accessibility scanning, and extensive documentation.
What's New
Agents (19 agents × 2 platforms = 38 agent files)
.claude/agents/) and GitHub Copilot (.github/agents/):accessibility-lead, aria-specialist, modal-specialist, contrast-master, keyboard-navigator, live-region-controller, forms-specialist, alt-text-headings, tables-data-specialist, testing-coach, wcag-guide
MCP Tools (9 total)
GitHub Copilot Integration
copilot-instructions.md— workspace-level accessibility guidancecopilot-review-instructions.md— PR review accessibility checkscopilot-commit-message-instructions.md— commit message standardsPULL_REQUEST_TEMPLATE.md— accessibility checklist for PRsCI/CD
a11y-check.yml— automated accessibility checks on PRsa11y-lint.mjs— HTML linting for accessibility issuesoffice-a11y-scan.mjs— Office document scanning in CIpdf-a11y-scan.mjs— PDF document scanning in CIDocumentation
example/Testing
node --checkpasses on all.mjsscripts andindex.jsJSON.parsevalidatesmanifest.jsonindex.js