Turn your issue queue into a living compliance document.
This toolkit automates the creation of "Evergreen" Accessibility Conformance Reports (ACR) by bridging the gap between active issue queues and compliance documentation. It extracts accessibility issues, analyzes them with AI, and generates valid OpenACR YAML & JSON files compatible with the Section 508 ACR Editor.
The concept of the "Evergreen ACR" was born from a frustration with the traditional compliance workflow. Historically, Accessibility Conformance Reports (ACRs/VPATs) were static documents, manually created once a year (or less), and often outdated the moment they were published. They failed to reflect the dynamic nature of modern software development.
This project aims to solve that by:
- Bridging the Gap: Directly connecting the "source of truth" (the issue queue) with the "compliance artifact" (the ACR).
- Incentivizing Reporting: If filing a bug automatically updates the compliance report, developers and users are more motivated to report detailed accessibility issues.
- Democratizing Compliance: By using open-source tools and local AI (Ollama), we remove the cost barriers to generating high-quality compliance documentation.
- Standardization: Adopting the OpenACR standard ensures that the data is machine-readable and interoperable with government tools.
The primary goal is to transform accessibility reporting from a static, annual snapshot into a dynamic, living process.
- π± Evergreen Compliance: Generate reports monthly that reflect the actual state of accessibility.
- π Incentivized Reporting: Tie official compliance directly to the issue queue, encouraging detailed bug reporting.
- π§ Actionable Intelligence: Move beyond "Pass/Fail" to identify specific versions, blockers, and remediation steps.
- π Privacy & Flexibility: Support both cloud-based AI (Google Gemini) and local AI (Ollama) for privacy and zero-cost operations.
This tool executes a 4-step pipeline to transform raw issue data into a Section 508-compliant report.
graph LR
A[Drupal.org / GitHub] -->|Step 1: Extract| B(Raw Issues CSV)
B -->|Step 2: Summarize <br/> π€ Gemini/Ollama| C(AI Summaries CSV)
C -->|Step 3: Consolidate <br/> π€ Gemini/Ollama| D(Consolidated CSV)
D -->|Step 4: Generate| E[OpenACR YAML/JSON]
style A fill:#f9f,stroke:#333,stroke-width:2px
style E fill:#9f9,stroke:#333,stroke-width:2px
- Extract: Crawls Drupal.org or GitHub for tickets tagged
accessibility,wcag, and specific SC tags (e.g.,wcag111,wcag21), capturing metadata. - Summarize: Uses AI to analyze issue descriptions, determining the specific WCAG Success Criterion (e.g., 1.1.1) and writing professional "ACR Notes."
- Consolidate: Groups issues by WCAG criterion to determine overall conformance levels (e.g., partially-supports).
- Generate: Outputs valid OpenACR YAML and JSON files.
- Python 3.9+
- Ollama (Optional, for local AI)
-
Clone the repository
git clone https://github.com/your-org/acr-generator.git cd acr-generator -
Set up Virtual Environment
python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate
-
Install Dependencies
pip install -r requirements.txt
-
Configure Environment Create a
.envfile in the root directory:GEMINI_API_KEY=your_api_key_here # Required if using Gemini backend
The master script run_acr.py orchestrates the entire pipeline. Results are saved in date-stamped directories (e.g., results/12-12-2025/).
Run the full pipeline using the default Google Gemini backend:
# For Drupal Projects (use project ID)
python run_acr.py --repo drupal
# For GitHub Repositories (use 'owner/repo' OR full URL)
python run_acr.py --repo ckeditor/ckeditor5
# OR
python run_acr.py --repo https://github.com/ckeditor/ckeditor5Run entirely locally to avoid API costs and keep data private:
python run_acr.py --repo drupal --ai-backend ollama --model gemma2:2bProcess only the first N issues (useful for testing):
# Process only first 10 issues
python run_acr.py --repo drupal --ai-backend ollama --model gemma2:2b --limit 10Show the script working against a large GitHub project by running the full pipeline for the Joomla repository. The steps below assume you have python3 available, are inside the repo root, and have already created and activated the virtual environment described in the Installing section so that pandas, python-dotenv, and the other dependencies are available.
# once (if not already done)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# run the Joomla scan
python run_acr.py --repo https://github.com/joomla/joomla-cms/Results land in results/joomla-joomla-cms-default-<date>; keep that folder (or the generated .zip) around if you want to move it into results/ for the comparator later.
You can override the default accessibility tags to scan for any topic:
python run_acr.py --repo drupal --tags "performance,sustainability"| Argument | Type | Default | Description |
|---|---|---|---|
--repo |
String | None | Drupal project ID (e.g. drupal) or GitHub repo (owner/repo or URL). |
--step |
Integer | All | Run a specific step (1, 2, 3, 4, or 5). |
--ai-backend |
String | gemini |
Choose AI backend: gemini (Cloud) or ollama (Local). |
--model |
String | None | Specific model name (e.g., gemma2:2b, llama3, gpt-oss:20b). |
--tags |
String | None | Comma-separated list of tags to search (overrides defaults). |
--limit |
Integer | None | Limit number of issues to process (useful for testing). |
--github-token |
String | None | GitHub Personal Access Token for higher API rate limits. |
--results-dir |
String | None | Use a specific results directory (overrides auto-generated name). |
When running steps 2-5, the script will automatically look for an existing results directory. If today's directory doesn't exist, it will search for and offer to use the most recent matching directory from a previous date.
# Explicitly use a specific directory from a previous run
python run_acr.py --repo joomla/joomla-cms --ai-backend ollama --model gemma3:4b --step 3 \
--results-dir joomla-joomla-cms-gemma34b-12-16-2025
# Or let the script auto-detect the most recent matching directory
python run_acr.py --repo joomla/joomla-cms --ai-backend ollama --model gemma3:4b --step 3
# If today's directory doesn't exist, you'll be prompted to use an earlier oneIf you encounter 403 API rate limit exceeded errors when scanning GitHub repositories, you can provide a Personal Access Token (PAT) to increase your limit (from 60 to 5,000 requests/hour).
- Generate a token at GitHub Settings > Tokens (no specific scopes needed for public repos).
- Pass it via the command line:
Or set it as an environment variable:
python run_acr.py --repo ckeditor/ckeditor5 --github-token YOUR_TOKEN_HERE
Or add it to yourexport GITHUB_TOKEN=your_token_here python run_acr.py ....envfile:GITHUB_TOKEN=your_token_here
Scrapes the issue queue for raw data.
python run_acr.py --repo drupal --step 1Output: results/wcag-detailed-issues_YYYY-MM-DD.csv
Analyzes issue descriptions and comments to generate compliance notes.
python run_acr.py --step 2 --ai-backend geminiOutput: results/wcag-issue-summaries_YYYY-MM-DD.csv
Groups individual issues by WCAG Success Criteria to form a "chapter" level view.
python run_acr.py --step 3Output: results/wcag-acr-consolidated_YYYY-MM-DD.csv
Converts the consolidated data into the final government-compliant YAML format.
python run_acr.py --step 4Output: results/drupal-openacr_YYYY-MM-DD.yaml
| File | Description | Key Columns |
|---|---|---|
| Detailed Issues | Raw scraping data | Issue ID, Status, Priority, Component |
| Summaries | AI-enriched data | ACR Note, Developer Note, WCAG Assessment |
| Consolidated | Chapter-level data | WCAG SC, Conformance Level, Remarks |
| OpenACR YAML | Final Report | Nested YAML structure conforming to Section 508 |
This repository includes an AGENTS.md file in the root directory. This file contains detailed context, coding conventions, and instructions specifically designed to help AI coding agents understand and work with this codebase effectively.
Contributions are welcome! Please follow these steps:
- Fork the project.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
Distributed under the AGPL License. See LICENSE for more information.
-
Place the scan directory inside
results/. Example:results/drupal-default-12-21-2025/containing the CSVs produced byrun_acr.py. -
Mark public-ready runs by touching
publish_readyinside the run folder (or runpython scripts/update_results_index.py --mark drupal-default-12-21-2025). This keeps experimental runs local-only. -
Regenerate the indexes via
python scripts/update_results_index.py. The script now writes:results/index.jsonβ tracked, contains only publishable runs for GitHub Pages.results/index.local.jsonβ ignored by Git, lists all runs. The UI automatically prefers this manifest onlocalhostor when loaded with?datasetIndex=local..gitignoreentries that whitelist only the publishable folders.
-
Rebuild comparator JSON (if you rely on aggregated outputs):
python build_comparator_json.py
-
Commit & push the new run plus
results/index.json(the local manifest stays ignored):git add results/drupal-default-12-21-2025 results/index.json .gitignore git commit -m "Add drupal-default-12-21-2025 scan and index entry" git push origin main
The comparator automatically uses the local manifest during development and the published manifest on GitHub Pages, so missing datasets will no longer break the homepage. Add ?datasetIndex=local (or ?datasetIndex=published) to the URL if you need to override the auto-detection.