agentic-qe 3.4.1 → 3.4.2
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/.claude/skills/.validation/README.md +111 -0
- package/.claude/skills/.validation/examples/chaos-engineering-output.example.json +530 -0
- package/.claude/skills/.validation/examples/performance-testing-output.example.json +252 -0
- package/.claude/skills/.validation/examples/security-testing-output.example.json +413 -0
- package/.claude/skills/.validation/examples/testability-scoring-output.example.json +350 -0
- package/.claude/skills/.validation/schemas/skill-eval.schema.json +452 -0
- package/.claude/skills/.validation/schemas/skill-frontmatter.schema.json +341 -0
- package/.claude/skills/.validation/schemas/skill-output-meta.schema.json +199 -0
- package/.claude/skills/.validation/schemas/skill-output.template.json +610 -0
- package/.claude/skills/.validation/skill-validation-mcp-integration.md +250 -0
- package/.claude/skills/.validation/templates/eval.template.yaml +366 -0
- package/.claude/skills/.validation/templates/schemas/output.json +145 -0
- package/.claude/skills/.validation/templates/security-testing-eval.template.yaml +725 -0
- package/.claude/skills/.validation/templates/skill-frontmatter.example.yaml +225 -0
- package/.claude/skills/.validation/templates/validate.template.sh +1060 -0
- package/.claude/skills/.validation/templates/validator-lib.sh +1031 -0
- package/.claude/skills/.validation/test-data/invalid-output.json +5 -0
- package/.claude/skills/.validation/test-data/minimal-output.json +9 -0
- package/.claude/skills/.validation/test-data/sample-output.json +73 -0
- package/.claude/skills/TRUST-TIERS.md +158 -0
- package/.claude/skills/a11y-ally/SKILL.md +1664 -1658
- package/.claude/skills/a11y-ally/evals/a11y-ally.yaml +376 -0
- package/.claude/skills/a11y-ally/schemas/output.json +549 -0
- package/.claude/skills/a11y-ally/scripts/validate.sh +690 -0
- package/.claude/skills/accessibility-testing/SKILL.md +8 -1
- package/.claude/skills/accessibility-testing/evals/accessibility-testing.yaml +719 -0
- package/.claude/skills/accessibility-testing/schemas/output.json +776 -0
- package/.claude/skills/accessibility-testing/scripts/validate.sh +943 -0
- package/.claude/skills/accessibility-testing/test-data/sample-output.json +191 -0
- package/.claude/skills/agentic-quality-engineering/SKILL.md +4 -0
- package/.claude/skills/agentic-quality-engineering/schemas/output.json +577 -0
- package/.claude/skills/api-testing-patterns/SKILL.md +5 -0
- package/.claude/skills/api-testing-patterns/evals/api-testing-patterns.yaml +696 -0
- package/.claude/skills/api-testing-patterns/schemas/output.json +845 -0
- package/.claude/skills/api-testing-patterns/scripts/validate.sh +931 -0
- package/.claude/skills/aqe-v2-v3-migration/schemas/output.json +513 -0
- package/.claude/skills/aqe-v2-v3-migration/skill.md +4 -0
- package/.claude/skills/brutal-honesty-review/SKILL.md +5 -0
- package/.claude/skills/brutal-honesty-review/schemas/output.json +291 -0
- package/.claude/skills/brutal-honesty-review/scripts/validate.sh +130 -0
- package/.claude/skills/bug-reporting-excellence/SKILL.md +5 -0
- package/.claude/skills/bug-reporting-excellence/schemas/output.json +288 -0
- package/.claude/skills/bug-reporting-excellence/scripts/validate.sh +108 -0
- package/.claude/skills/chaos-engineering-resilience/SKILL.md +5 -0
- package/.claude/skills/chaos-engineering-resilience/evals/chaos-engineering-resilience.yaml +761 -0
- package/.claude/skills/chaos-engineering-resilience/schemas/output.json +1205 -0
- package/.claude/skills/chaos-engineering-resilience/scripts/validate.sh +1107 -0
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +6 -0
- package/.claude/skills/cicd-pipeline-qe-orchestrator/evals/cicd-pipeline-qe-orchestrator.yaml +157 -0
- package/.claude/skills/cicd-pipeline-qe-orchestrator/schemas/output.json +542 -0
- package/.claude/skills/cicd-pipeline-qe-orchestrator/scripts/validate.sh +310 -0
- package/.claude/skills/code-review-quality/SKILL.md +5 -0
- package/.claude/skills/code-review-quality/schemas/output.json +264 -0
- package/.claude/skills/code-review-quality/scripts/validate.sh +113 -0
- package/.claude/skills/compatibility-testing/evals/compatibility-testing.yaml +410 -0
- package/.claude/skills/compatibility-testing/schemas/output.json +551 -0
- package/.claude/skills/compatibility-testing/scripts/validate.sh +605 -0
- package/.claude/skills/compliance-testing/SKILL.md +7 -0
- package/.claude/skills/compliance-testing/evals/compliance-testing.yaml +1107 -0
- package/.claude/skills/compliance-testing/schemas/output.json +845 -0
- package/.claude/skills/compliance-testing/scripts/validate.sh +888 -0
- package/.claude/skills/consultancy-practices/SKILL.md +4 -0
- package/.claude/skills/consultancy-practices/schemas/output.json +282 -0
- package/.claude/skills/context-driven-testing/SKILL.md +3 -0
- package/.claude/skills/contract-testing/SKILL.md +5 -0
- package/.claude/skills/contract-testing/evals/contract-testing.yaml +748 -0
- package/.claude/skills/contract-testing/schemas/output.json +638 -0
- package/.claude/skills/contract-testing/scripts/validate.sh +1033 -0
- package/.claude/skills/database-testing/SKILL.md +5 -0
- package/.claude/skills/database-testing/evals/database-testing.yaml +968 -0
- package/.claude/skills/database-testing/schemas/output.json +1446 -0
- package/.claude/skills/database-testing/scripts/validate.sh +1099 -0
- package/.claude/skills/exploratory-testing-advanced/SKILL.md +3 -0
- package/.claude/skills/holistic-testing-pact/SKILL.md +3 -0
- package/.claude/skills/localization-testing/SKILL.md +6 -0
- package/.claude/skills/localization-testing/evals/localization-testing.yaml +544 -0
- package/.claude/skills/localization-testing/schemas/output.json +325 -0
- package/.claude/skills/localization-testing/scripts/validate.sh +131 -0
- package/.claude/skills/mobile-testing/SKILL.md +6 -0
- package/.claude/skills/mobile-testing/evals/mobile-testing.yaml +537 -0
- package/.claude/skills/mobile-testing/schemas/output.json +318 -0
- package/.claude/skills/mobile-testing/scripts/validate.sh +127 -0
- package/.claude/skills/mutation-testing/SKILL.md +8 -1
- package/.claude/skills/mutation-testing/evals/mutation-testing.yaml +652 -0
- package/.claude/skills/mutation-testing/schemas/output.json +707 -0
- package/.claude/skills/mutation-testing/scripts/validate.sh +992 -0
- package/.claude/skills/mutation-testing/test-data/sample-output.json +295 -0
- package/.claude/skills/n8n-expression-testing/SKILL.md +6 -0
- package/.claude/skills/n8n-expression-testing/evals/n8n-expression-testing.yaml +450 -0
- package/.claude/skills/n8n-expression-testing/schemas/output.json +369 -0
- package/.claude/skills/n8n-expression-testing/scripts/validate.sh +162 -0
- package/.claude/skills/n8n-integration-testing-patterns/SKILL.md +6 -0
- package/.claude/skills/n8n-integration-testing-patterns/evals/n8n-integration-testing-patterns.yaml +522 -0
- package/.claude/skills/n8n-integration-testing-patterns/schemas/output.json +291 -0
- package/.claude/skills/n8n-integration-testing-patterns/scripts/validate.sh +104 -0
- package/.claude/skills/n8n-security-testing/SKILL.md +6 -0
- package/.claude/skills/n8n-security-testing/evals/n8n-security-testing.yaml +493 -0
- package/.claude/skills/n8n-security-testing/schemas/output.json +293 -0
- package/.claude/skills/n8n-security-testing/scripts/validate.sh +120 -0
- package/.claude/skills/n8n-trigger-testing-strategies/SKILL.md +6 -0
- package/.claude/skills/n8n-trigger-testing-strategies/evals/n8n-trigger-testing-strategies.yaml +500 -0
- package/.claude/skills/n8n-trigger-testing-strategies/schemas/output.json +295 -0
- package/.claude/skills/n8n-trigger-testing-strategies/scripts/validate.sh +121 -0
- package/.claude/skills/n8n-workflow-testing-fundamentals/SKILL.md +6 -0
- package/.claude/skills/n8n-workflow-testing-fundamentals/evals/n8n-workflow-testing-fundamentals.yaml +497 -0
- package/.claude/skills/n8n-workflow-testing-fundamentals/schemas/output.json +254 -0
- package/.claude/skills/n8n-workflow-testing-fundamentals/scripts/validate.sh +126 -0
- package/.claude/skills/performance-analysis/SKILL.md +6 -0
- package/.claude/skills/performance-analysis/evals/performance-analysis.yaml +144 -0
- package/.claude/skills/performance-analysis/schemas/output.json +588 -0
- package/.claude/skills/performance-analysis/scripts/validate.sh +63 -0
- package/.claude/skills/performance-testing/SKILL.md +5 -0
- package/.claude/skills/performance-testing/evals/performance-testing.yaml +772 -0
- package/.claude/skills/performance-testing/schemas/output.json +1184 -0
- package/.claude/skills/performance-testing/scripts/validate.sh +1090 -0
- package/.claude/skills/qcsd-ideation-swarm/SKILL.md +1759 -1753
- package/.claude/skills/qcsd-ideation-swarm/evals/qcsd-ideation-swarm.yaml +138 -0
- package/.claude/skills/qcsd-ideation-swarm/schemas/output.json +568 -0
- package/.claude/skills/qcsd-ideation-swarm/scripts/validate.sh +56 -0
- package/.claude/skills/qe-chaos-resilience/SKILL.md +6 -0
- package/.claude/skills/qe-chaos-resilience/evals/qe-chaos-resilience.yaml +443 -0
- package/.claude/skills/qe-chaos-resilience/schemas/output.json +314 -0
- package/.claude/skills/qe-chaos-resilience/scripts/validate.sh +401 -0
- package/.claude/skills/qe-code-intelligence/SKILL.md +6 -0
- package/.claude/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +459 -0
- package/.claude/skills/qe-code-intelligence/schemas/output.json +315 -0
- package/.claude/skills/qe-code-intelligence/scripts/validate.sh +408 -0
- package/.claude/skills/qe-contract-testing/SKILL.md +6 -0
- package/.claude/skills/qe-contract-testing/evals/qe-contract-testing.yaml +513 -0
- package/.claude/skills/qe-contract-testing/schemas/output.json +295 -0
- package/.claude/skills/qe-contract-testing/scripts/validate.sh +421 -0
- package/.claude/skills/qe-coverage-analysis/SKILL.md +6 -0
- package/.claude/skills/qe-coverage-analysis/evals/qe-coverage-analysis.yaml +494 -0
- package/.claude/skills/qe-coverage-analysis/schemas/output.json +286 -0
- package/.claude/skills/qe-coverage-analysis/scripts/validate.sh +453 -0
- package/.claude/skills/qe-defect-intelligence/SKILL.md +6 -0
- package/.claude/skills/qe-defect-intelligence/evals/qe-defect-intelligence.yaml +511 -0
- package/.claude/skills/qe-defect-intelligence/schemas/output.json +283 -0
- package/.claude/skills/qe-defect-intelligence/scripts/validate.sh +466 -0
- package/.claude/skills/qe-iterative-loop/SKILL.md +445 -440
- package/.claude/skills/qe-iterative-loop/schemas/output.json +264 -0
- package/.claude/skills/qe-iterative-loop/scripts/validate.sh +474 -0
- package/.claude/skills/qe-learning-optimization/SKILL.md +6 -0
- package/.claude/skills/qe-learning-optimization/evals/qe-learning-optimization.yaml +144 -0
- package/.claude/skills/qe-learning-optimization/schemas/output.json +288 -0
- package/.claude/skills/qe-learning-optimization/scripts/validate.sh +56 -0
- package/.claude/skills/qe-quality-assessment/SKILL.md +6 -0
- package/.claude/skills/qe-quality-assessment/evals/qe-quality-assessment.yaml +506 -0
- package/.claude/skills/qe-quality-assessment/schemas/output.json +550 -0
- package/.claude/skills/qe-quality-assessment/scripts/validate.sh +352 -0
- package/.claude/skills/qe-requirements-validation/SKILL.md +6 -0
- package/.claude/skills/qe-requirements-validation/evals/qe-requirements-validation.yaml +598 -0
- package/.claude/skills/qe-requirements-validation/schemas/output.json +587 -0
- package/.claude/skills/qe-requirements-validation/scripts/validate.sh +275 -0
- package/.claude/skills/qe-security-compliance/SKILL.md +6 -0
- package/.claude/skills/qe-security-compliance/evals/qe-security-compliance.yaml +595 -0
- package/.claude/skills/qe-security-compliance/schemas/output.json +498 -0
- package/.claude/skills/qe-security-compliance/scripts/validate.sh +305 -0
- package/.claude/skills/qe-test-execution/SKILL.md +6 -0
- package/.claude/skills/qe-test-execution/evals/qe-test-execution.yaml +607 -0
- package/.claude/skills/qe-test-execution/schemas/output.json +529 -0
- package/.claude/skills/qe-test-execution/scripts/validate.sh +323 -0
- package/.claude/skills/qe-test-generation/SKILL.md +6 -0
- package/.claude/skills/qe-test-generation/evals/qe-test-generation.yaml +148 -0
- package/.claude/skills/qe-test-generation/schemas/output.json +439 -0
- package/.claude/skills/qe-test-generation/scripts/validate.sh +56 -0
- package/.claude/skills/qe-visual-accessibility/SKILL.md +6 -0
- package/.claude/skills/qe-visual-accessibility/evals/qe-visual-accessibility.yaml +142 -0
- package/.claude/skills/qe-visual-accessibility/schemas/output.json +491 -0
- package/.claude/skills/qe-visual-accessibility/scripts/validate.sh +56 -0
- package/.claude/skills/quality-metrics/SKILL.md +6 -0
- package/.claude/skills/quality-metrics/evals/quality-metrics.yaml +494 -0
- package/.claude/skills/quality-metrics/schemas/output.json +403 -0
- package/.claude/skills/quality-metrics/scripts/validate.sh +434 -0
- package/.claude/skills/refactoring-patterns/SKILL.md +5 -0
- package/.claude/skills/refactoring-patterns/schemas/output.json +475 -0
- package/.claude/skills/refactoring-patterns/scripts/validate.sh +241 -0
- package/.claude/skills/regression-testing/SKILL.md +6 -0
- package/.claude/skills/regression-testing/evals/regression-testing.yaml +504 -0
- package/.claude/skills/regression-testing/schemas/output.json +311 -0
- package/.claude/skills/regression-testing/scripts/validate.sh +130 -0
- package/.claude/skills/risk-based-testing/SKILL.md +6 -0
- package/.claude/skills/risk-based-testing/evals/risk-based-testing.yaml +141 -0
- package/.claude/skills/risk-based-testing/schemas/output.json +480 -0
- package/.claude/skills/risk-based-testing/scripts/validate.sh +56 -0
- package/.claude/skills/security-testing/SKILL.md +5 -0
- package/.claude/skills/security-testing/evals/security-testing.yaml +789 -0
- package/.claude/skills/security-testing/schemas/output.json +879 -0
- package/.claude/skills/security-testing/scripts/validate.sh +967 -0
- package/.claude/skills/security-visual-testing/SKILL.md +223 -217
- package/.claude/skills/security-visual-testing/evals/security-visual-testing.yaml +163 -0
- package/.claude/skills/security-visual-testing/schemas/output.json +486 -0
- package/.claude/skills/security-visual-testing/scripts/validate.sh +748 -0
- package/.claude/skills/sherlock-review/SKILL.md +5 -0
- package/.claude/skills/sherlock-review/schemas/output.json +297 -0
- package/.claude/skills/sherlock-review/scripts/validate.sh +115 -0
- package/.claude/skills/shift-left-testing/SKILL.md +6 -0
- package/.claude/skills/shift-left-testing/evals/shift-left-testing.yaml +145 -0
- package/.claude/skills/shift-left-testing/schemas/output.json +459 -0
- package/.claude/skills/shift-left-testing/scripts/validate.sh +56 -0
- package/.claude/skills/shift-right-testing/SKILL.md +6 -0
- package/.claude/skills/shift-right-testing/evals/shift-right-testing.yaml +147 -0
- package/.claude/skills/shift-right-testing/schemas/output.json +418 -0
- package/.claude/skills/shift-right-testing/scripts/validate.sh +56 -0
- package/.claude/skills/six-thinking-hats/SKILL.md +3 -0
- package/.claude/skills/tdd-london-chicago/SKILL.md +5 -0
- package/.claude/skills/tdd-london-chicago/schemas/output.json +444 -0
- package/.claude/skills/tdd-london-chicago/scripts/validate.sh +214 -0
- package/.claude/skills/technical-writing/SKILL.md +4 -0
- package/.claude/skills/technical-writing/schemas/output.json +268 -0
- package/.claude/skills/test-automation-strategy/SKILL.md +6 -0
- package/.claude/skills/test-automation-strategy/evals/test-automation-strategy.yaml +148 -0
- package/.claude/skills/test-automation-strategy/schemas/output.json +444 -0
- package/.claude/skills/test-automation-strategy/scripts/validate.sh +195 -0
- package/.claude/skills/test-data-management/SKILL.md +6 -0
- package/.claude/skills/test-data-management/evals/test-data-management.yaml +504 -0
- package/.claude/skills/test-data-management/schemas/output.json +284 -0
- package/.claude/skills/test-data-management/scripts/validate.sh +137 -0
- package/.claude/skills/test-design-techniques/SKILL.md +6 -0
- package/.claude/skills/test-design-techniques/evals/test-design-techniques.yaml +142 -0
- package/.claude/skills/test-design-techniques/schemas/output.json +295 -0
- package/.claude/skills/test-design-techniques/scripts/validate.sh +91 -0
- package/.claude/skills/test-environment-management/SKILL.md +4 -0
- package/.claude/skills/test-environment-management/schemas/output.json +310 -0
- package/.claude/skills/test-reporting-analytics/SKILL.md +6 -0
- package/.claude/skills/test-reporting-analytics/evals/test-reporting-analytics.yaml +155 -0
- package/.claude/skills/test-reporting-analytics/schemas/output.json +329 -0
- package/.claude/skills/test-reporting-analytics/scripts/validate.sh +77 -0
- package/.claude/skills/testability-scoring/SKILL.md +5 -0
- package/.claude/skills/testability-scoring/evals/testability-scoring.yaml +814 -0
- package/.claude/skills/testability-scoring/schemas/output.json +606 -0
- package/.claude/skills/testability-scoring/scripts/validate.sh +891 -0
- package/.claude/skills/trust-tier-manifest.json +2333 -0
- package/.claude/skills/verification-quality/SKILL.md +6 -0
- package/.claude/skills/verification-quality/evals/verification-quality.yaml +150 -0
- package/.claude/skills/verification-quality/schemas/output.json +432 -0
- package/.claude/skills/verification-quality/scripts/validate.sh +77 -0
- package/.claude/skills/visual-testing-advanced/SKILL.md +6 -0
- package/.claude/skills/visual-testing-advanced/evals/visual-testing-advanced.yaml +154 -0
- package/.claude/skills/visual-testing-advanced/schemas/output.json +294 -0
- package/.claude/skills/visual-testing-advanced/scripts/validate.sh +77 -0
- package/.claude/skills/xp-practices/SKILL.md +3 -0
- package/README.md +39 -2
- package/package.json +4 -1
- package/scripts/run-skill-eval.ts +1097 -0
- package/scripts/test-schema-validation.js +301 -0
- package/scripts/update-skill-manifest.ts +751 -0
- package/scripts/validate-skill-frontmatter.js +141 -0
- package/v3/CHANGELOG.md +21 -0
- package/v3/README.md +43 -3
- package/v3/assets/agents/v3/qe-test-idea-rewriter.md +375 -375
- package/v3/assets/skills/.validation/README.md +111 -0
- package/v3/assets/skills/.validation/examples/chaos-engineering-output.example.json +530 -0
- package/v3/assets/skills/.validation/examples/performance-testing-output.example.json +252 -0
- package/v3/assets/skills/.validation/examples/security-testing-output.example.json +413 -0
- package/v3/assets/skills/.validation/examples/testability-scoring-output.example.json +350 -0
- package/v3/assets/skills/.validation/schemas/skill-eval.schema.json +452 -0
- package/v3/assets/skills/.validation/schemas/skill-frontmatter.schema.json +341 -0
- package/v3/assets/skills/.validation/schemas/skill-output-meta.schema.json +199 -0
- package/v3/assets/skills/.validation/schemas/skill-output.template.json +610 -0
- package/v3/assets/skills/.validation/skill-validation-mcp-integration.md +250 -0
- package/v3/assets/skills/.validation/templates/eval.template.yaml +366 -0
- package/v3/assets/skills/.validation/templates/schemas/output.json +145 -0
- package/v3/assets/skills/.validation/templates/security-testing-eval.template.yaml +725 -0
- package/v3/assets/skills/.validation/templates/skill-frontmatter.example.yaml +225 -0
- package/v3/assets/skills/.validation/templates/validate.template.sh +1060 -0
- package/v3/assets/skills/.validation/templates/validator-lib.sh +1031 -0
- package/v3/assets/skills/.validation/test-data/invalid-output.json +5 -0
- package/v3/assets/skills/.validation/test-data/minimal-output.json +9 -0
- package/v3/assets/skills/.validation/test-data/sample-output.json +73 -0
- package/v3/assets/skills/accessibility-testing/SKILL.md +8 -1
- package/v3/assets/skills/accessibility-testing/evals/accessibility-testing.yaml +719 -0
- package/v3/assets/skills/accessibility-testing/schemas/output.json +776 -0
- package/v3/assets/skills/accessibility-testing/scripts/validate.sh +943 -0
- package/v3/assets/skills/accessibility-testing/test-data/sample-output.json +191 -0
- package/v3/assets/skills/agentic-quality-engineering/SKILL.md +4 -0
- package/v3/assets/skills/agentic-quality-engineering/schemas/output.json +577 -0
- package/v3/assets/skills/api-testing-patterns/SKILL.md +5 -0
- package/v3/assets/skills/api-testing-patterns/evals/api-testing-patterns.yaml +696 -0
- package/v3/assets/skills/api-testing-patterns/schemas/output.json +845 -0
- package/v3/assets/skills/api-testing-patterns/scripts/validate.sh +931 -0
- package/v3/assets/skills/aqe-v2-v3-migration/schemas/output.json +513 -0
- package/v3/assets/skills/aqe-v2-v3-migration/skill.md +20 -16
- package/v3/assets/skills/bug-reporting-excellence/SKILL.md +5 -0
- package/v3/assets/skills/bug-reporting-excellence/schemas/output.json +288 -0
- package/v3/assets/skills/bug-reporting-excellence/scripts/validate.sh +108 -0
- package/v3/assets/skills/chaos-engineering-resilience/SKILL.md +5 -0
- package/v3/assets/skills/chaos-engineering-resilience/evals/chaos-engineering-resilience.yaml +761 -0
- package/v3/assets/skills/chaos-engineering-resilience/schemas/output.json +1205 -0
- package/v3/assets/skills/chaos-engineering-resilience/scripts/validate.sh +1107 -0
- package/v3/assets/skills/code-review-quality/SKILL.md +5 -0
- package/v3/assets/skills/code-review-quality/schemas/output.json +264 -0
- package/v3/assets/skills/code-review-quality/scripts/validate.sh +113 -0
- package/v3/assets/skills/compatibility-testing/evals/compatibility-testing.yaml +410 -0
- package/v3/assets/skills/compatibility-testing/schemas/output.json +551 -0
- package/v3/assets/skills/compatibility-testing/scripts/validate.sh +605 -0
- package/v3/assets/skills/compliance-testing/SKILL.md +7 -0
- package/v3/assets/skills/compliance-testing/evals/compliance-testing.yaml +1107 -0
- package/v3/assets/skills/compliance-testing/schemas/output.json +845 -0
- package/v3/assets/skills/compliance-testing/scripts/validate.sh +888 -0
- package/v3/assets/skills/consultancy-practices/SKILL.md +4 -0
- package/v3/assets/skills/consultancy-practices/schemas/output.json +282 -0
- package/v3/assets/skills/context-driven-testing/SKILL.md +3 -0
- package/v3/assets/skills/contract-testing/SKILL.md +5 -0
- package/v3/assets/skills/contract-testing/evals/contract-testing.yaml +748 -0
- package/v3/assets/skills/contract-testing/schemas/output.json +638 -0
- package/v3/assets/skills/contract-testing/scripts/validate.sh +1033 -0
- package/v3/assets/skills/database-testing/SKILL.md +5 -0
- package/v3/assets/skills/database-testing/evals/database-testing.yaml +968 -0
- package/v3/assets/skills/database-testing/schemas/output.json +1446 -0
- package/v3/assets/skills/database-testing/scripts/validate.sh +1099 -0
- package/v3/assets/skills/exploratory-testing-advanced/SKILL.md +3 -0
- package/v3/assets/skills/holistic-testing-pact/SKILL.md +3 -0
- package/v3/assets/skills/localization-testing/SKILL.md +6 -0
- package/v3/assets/skills/localization-testing/evals/localization-testing.yaml +544 -0
- package/v3/assets/skills/localization-testing/schemas/output.json +325 -0
- package/v3/assets/skills/localization-testing/scripts/validate.sh +131 -0
- package/v3/assets/skills/mobile-testing/SKILL.md +6 -0
- package/v3/assets/skills/mobile-testing/evals/mobile-testing.yaml +537 -0
- package/v3/assets/skills/mobile-testing/schemas/output.json +318 -0
- package/v3/assets/skills/mobile-testing/scripts/validate.sh +127 -0
- package/v3/assets/skills/mutation-testing/SKILL.md +8 -1
- package/v3/assets/skills/mutation-testing/evals/mutation-testing.yaml +652 -0
- package/v3/assets/skills/mutation-testing/schemas/output.json +707 -0
- package/v3/assets/skills/mutation-testing/scripts/validate.sh +992 -0
- package/v3/assets/skills/mutation-testing/test-data/sample-output.json +295 -0
- package/v3/assets/skills/n8n-expression-testing/scripts/validate.sh +162 -0
- package/v3/assets/skills/n8n-integration-testing-patterns/scripts/validate.sh +104 -0
- package/v3/assets/skills/n8n-security-testing/scripts/validate.sh +120 -0
- package/v3/assets/skills/n8n-trigger-testing-strategies/scripts/validate.sh +121 -0
- package/v3/assets/skills/n8n-workflow-testing-fundamentals/scripts/validate.sh +126 -0
- package/v3/assets/skills/performance-testing/SKILL.md +5 -0
- package/v3/assets/skills/performance-testing/evals/performance-testing.yaml +772 -0
- package/v3/assets/skills/performance-testing/schemas/output.json +1184 -0
- package/v3/assets/skills/performance-testing/scripts/validate.sh +1090 -0
- package/v3/assets/skills/qe-chaos-resilience/SKILL.md +6 -0
- package/v3/assets/skills/qe-chaos-resilience/evals/qe-chaos-resilience.yaml +443 -0
- package/v3/assets/skills/qe-chaos-resilience/schemas/output.json +314 -0
- package/v3/assets/skills/qe-chaos-resilience/scripts/validate.sh +401 -0
- package/v3/assets/skills/qe-code-intelligence/SKILL.md +6 -0
- package/v3/assets/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +459 -0
- package/v3/assets/skills/qe-code-intelligence/schemas/output.json +315 -0
- package/v3/assets/skills/qe-code-intelligence/scripts/validate.sh +408 -0
- package/v3/assets/skills/qe-contract-testing/SKILL.md +6 -0
- package/v3/assets/skills/qe-contract-testing/evals/qe-contract-testing.yaml +513 -0
- package/v3/assets/skills/qe-contract-testing/schemas/output.json +295 -0
- package/v3/assets/skills/qe-contract-testing/scripts/validate.sh +421 -0
- package/v3/assets/skills/qe-coverage-analysis/SKILL.md +6 -0
- package/v3/assets/skills/qe-coverage-analysis/evals/qe-coverage-analysis.yaml +494 -0
- package/v3/assets/skills/qe-coverage-analysis/schemas/output.json +286 -0
- package/v3/assets/skills/qe-coverage-analysis/scripts/validate.sh +453 -0
- package/v3/assets/skills/qe-defect-intelligence/SKILL.md +6 -0
- package/v3/assets/skills/qe-defect-intelligence/evals/qe-defect-intelligence.yaml +511 -0
- package/v3/assets/skills/qe-defect-intelligence/schemas/output.json +283 -0
- package/v3/assets/skills/qe-defect-intelligence/scripts/validate.sh +466 -0
- package/v3/assets/skills/qe-iterative-loop/SKILL.md +445 -443
- package/v3/assets/skills/qe-iterative-loop/schemas/output.json +264 -0
- package/v3/assets/skills/qe-iterative-loop/scripts/validate.sh +474 -0
- package/v3/assets/skills/qe-learning-optimization/SKILL.md +6 -0
- package/v3/assets/skills/qe-learning-optimization/evals/qe-learning-optimization.yaml +144 -0
- package/v3/assets/skills/qe-learning-optimization/schemas/output.json +288 -0
- package/v3/assets/skills/qe-learning-optimization/scripts/validate.sh +56 -0
- package/v3/assets/skills/qe-quality-assessment/SKILL.md +6 -0
- package/v3/assets/skills/qe-quality-assessment/evals/qe-quality-assessment.yaml +506 -0
- package/v3/assets/skills/qe-quality-assessment/schemas/output.json +550 -0
- package/v3/assets/skills/qe-quality-assessment/scripts/validate.sh +352 -0
- package/v3/assets/skills/qe-requirements-validation/SKILL.md +6 -0
- package/v3/assets/skills/qe-requirements-validation/evals/qe-requirements-validation.yaml +598 -0
- package/v3/assets/skills/qe-requirements-validation/schemas/output.json +587 -0
- package/v3/assets/skills/qe-requirements-validation/scripts/validate.sh +275 -0
- package/v3/assets/skills/qe-security-compliance/SKILL.md +6 -0
- package/v3/assets/skills/qe-security-compliance/evals/qe-security-compliance.yaml +595 -0
- package/v3/assets/skills/qe-security-compliance/schemas/output.json +498 -0
- package/v3/assets/skills/qe-security-compliance/scripts/validate.sh +305 -0
- package/v3/assets/skills/qe-test-execution/SKILL.md +6 -0
- package/v3/assets/skills/qe-test-execution/evals/qe-test-execution.yaml +607 -0
- package/v3/assets/skills/qe-test-execution/schemas/output.json +529 -0
- package/v3/assets/skills/qe-test-execution/scripts/validate.sh +323 -0
- package/v3/assets/skills/qe-test-generation/SKILL.md +6 -0
- package/v3/assets/skills/qe-test-generation/evals/qe-test-generation.yaml +148 -0
- package/v3/assets/skills/qe-test-generation/schemas/output.json +439 -0
- package/v3/assets/skills/qe-test-generation/scripts/validate.sh +56 -0
- package/v3/assets/skills/qe-visual-accessibility/SKILL.md +6 -0
- package/v3/assets/skills/qe-visual-accessibility/evals/qe-visual-accessibility.yaml +142 -0
- package/v3/assets/skills/qe-visual-accessibility/schemas/output.json +491 -0
- package/v3/assets/skills/qe-visual-accessibility/scripts/validate.sh +56 -0
- package/v3/assets/skills/quality-metrics/SKILL.md +6 -0
- package/v3/assets/skills/quality-metrics/evals/quality-metrics.yaml +494 -0
- package/v3/assets/skills/quality-metrics/schemas/output.json +403 -0
- package/v3/assets/skills/quality-metrics/scripts/validate.sh +434 -0
- package/v3/assets/skills/refactoring-patterns/SKILL.md +5 -0
- package/v3/assets/skills/refactoring-patterns/schemas/output.json +475 -0
- package/v3/assets/skills/refactoring-patterns/scripts/validate.sh +241 -0
- package/v3/assets/skills/regression-testing/SKILL.md +6 -0
- package/v3/assets/skills/regression-testing/evals/regression-testing.yaml +504 -0
- package/v3/assets/skills/regression-testing/schemas/output.json +311 -0
- package/v3/assets/skills/regression-testing/scripts/validate.sh +130 -0
- package/v3/assets/skills/risk-based-testing/SKILL.md +6 -0
- package/v3/assets/skills/risk-based-testing/evals/risk-based-testing.yaml +141 -0
- package/v3/assets/skills/risk-based-testing/schemas/output.json +480 -0
- package/v3/assets/skills/risk-based-testing/scripts/validate.sh +56 -0
- package/v3/assets/skills/security-testing/SKILL.md +5 -0
- package/v3/assets/skills/security-testing/evals/security-testing.yaml +789 -0
- package/v3/assets/skills/security-testing/schemas/output.json +879 -0
- package/v3/assets/skills/security-testing/scripts/validate.sh +967 -0
- package/v3/assets/skills/shift-left-testing/SKILL.md +6 -0
- package/v3/assets/skills/shift-left-testing/evals/shift-left-testing.yaml +145 -0
- package/v3/assets/skills/shift-left-testing/schemas/output.json +459 -0
- package/v3/assets/skills/shift-left-testing/scripts/validate.sh +56 -0
- package/v3/assets/skills/shift-right-testing/SKILL.md +6 -0
- package/v3/assets/skills/shift-right-testing/evals/shift-right-testing.yaml +147 -0
- package/v3/assets/skills/shift-right-testing/schemas/output.json +418 -0
- package/v3/assets/skills/shift-right-testing/scripts/validate.sh +56 -0
- package/v3/assets/skills/six-thinking-hats/SKILL.md +3 -0
- package/v3/assets/skills/tdd-london-chicago/SKILL.md +5 -0
- package/v3/assets/skills/tdd-london-chicago/schemas/output.json +444 -0
- package/v3/assets/skills/tdd-london-chicago/scripts/validate.sh +214 -0
- package/v3/assets/skills/technical-writing/SKILL.md +4 -0
- package/v3/assets/skills/technical-writing/schemas/output.json +268 -0
- package/v3/assets/skills/test-automation-strategy/SKILL.md +6 -0
- package/v3/assets/skills/test-automation-strategy/evals/test-automation-strategy.yaml +148 -0
- package/v3/assets/skills/test-automation-strategy/schemas/output.json +444 -0
- package/v3/assets/skills/test-automation-strategy/scripts/validate.sh +195 -0
- package/v3/assets/skills/test-data-management/SKILL.md +6 -0
- package/v3/assets/skills/test-data-management/evals/test-data-management.yaml +504 -0
- package/v3/assets/skills/test-data-management/schemas/output.json +284 -0
- package/v3/assets/skills/test-data-management/scripts/validate.sh +137 -0
- package/v3/assets/skills/test-design-techniques/SKILL.md +6 -0
- package/v3/assets/skills/test-design-techniques/evals/test-design-techniques.yaml +142 -0
- package/v3/assets/skills/test-design-techniques/schemas/output.json +295 -0
- package/v3/assets/skills/test-design-techniques/scripts/validate.sh +91 -0
- package/v3/assets/skills/test-environment-management/SKILL.md +4 -0
- package/v3/assets/skills/test-environment-management/schemas/output.json +310 -0
- package/v3/assets/skills/test-reporting-analytics/SKILL.md +6 -0
- package/v3/assets/skills/test-reporting-analytics/evals/test-reporting-analytics.yaml +155 -0
- package/v3/assets/skills/test-reporting-analytics/schemas/output.json +329 -0
- package/v3/assets/skills/test-reporting-analytics/scripts/validate.sh +77 -0
- package/v3/assets/skills/verification-quality/SKILL.md +6 -0
- package/v3/assets/skills/verification-quality/evals/verification-quality.yaml +150 -0
- package/v3/assets/skills/verification-quality/schemas/output.json +432 -0
- package/v3/assets/skills/verification-quality/scripts/validate.sh +77 -0
- package/v3/assets/skills/visual-testing-advanced/SKILL.md +6 -0
- package/v3/assets/skills/visual-testing-advanced/evals/visual-testing-advanced.yaml +154 -0
- package/v3/assets/skills/visual-testing-advanced/schemas/output.json +294 -0
- package/v3/assets/skills/visual-testing-advanced/scripts/validate.sh +77 -0
- package/v3/assets/skills/xp-practices/SKILL.md +3 -0
- package/v3/assets/templates/validation-report.md.hbs +139 -0
- package/v3/assets/templates/validation-summary.json +56 -0
- package/v3/dist/cli/bundle.js +7368 -3418
- package/v3/dist/cli/commands/eval.d.ts +18 -0
- package/v3/dist/cli/commands/eval.d.ts.map +1 -0
- package/v3/dist/cli/commands/eval.js +505 -0
- package/v3/dist/cli/commands/eval.js.map +1 -0
- package/v3/dist/cli/commands/validate-swarm.d.ts +16 -0
- package/v3/dist/cli/commands/validate-swarm.d.ts.map +1 -0
- package/v3/dist/cli/commands/validate-swarm.js +251 -0
- package/v3/dist/cli/commands/validate-swarm.js.map +1 -0
- package/v3/dist/cli/commands/validate.d.ts +14 -0
- package/v3/dist/cli/commands/validate.d.ts.map +1 -0
- package/v3/dist/cli/commands/validate.js +408 -0
- package/v3/dist/cli/commands/validate.js.map +1 -0
- package/v3/dist/cli/index.js +6 -0
- package/v3/dist/cli/index.js.map +1 -1
- package/v3/dist/index.d.ts +2 -0
- package/v3/dist/index.d.ts.map +1 -1
- package/v3/dist/index.js +10 -0
- package/v3/dist/index.js.map +1 -1
- package/v3/dist/init/skills-installer.d.ts +6 -0
- package/v3/dist/init/skills-installer.d.ts.map +1 -1
- package/v3/dist/init/skills-installer.js +48 -0
- package/v3/dist/init/skills-installer.js.map +1 -1
- package/v3/dist/learning/index.d.ts +2 -0
- package/v3/dist/learning/index.d.ts.map +1 -1
- package/v3/dist/learning/index.js +4 -0
- package/v3/dist/learning/index.js.map +1 -1
- package/v3/dist/learning/skill-validation-learner.d.ts +264 -0
- package/v3/dist/learning/skill-validation-learner.d.ts.map +1 -0
- package/v3/dist/learning/skill-validation-learner.js +515 -0
- package/v3/dist/learning/skill-validation-learner.js.map +1 -0
- package/v3/dist/validation/index.d.ts +19 -0
- package/v3/dist/validation/index.d.ts.map +1 -0
- package/v3/dist/validation/index.js +31 -0
- package/v3/dist/validation/index.js.map +1 -0
- package/v3/dist/validation/parallel-eval-runner.d.ts +307 -0
- package/v3/dist/validation/parallel-eval-runner.d.ts.map +1 -0
- package/v3/dist/validation/parallel-eval-runner.js +566 -0
- package/v3/dist/validation/parallel-eval-runner.js.map +1 -0
- package/v3/dist/validation/swarm-skill-validator.d.ts +282 -0
- package/v3/dist/validation/swarm-skill-validator.d.ts.map +1 -0
- package/v3/dist/validation/swarm-skill-validator.js +460 -0
- package/v3/dist/validation/swarm-skill-validator.js.map +1 -0
- package/v3/dist/validation/validation-result-aggregator.d.ts +232 -0
- package/v3/dist/validation/validation-result-aggregator.d.ts.map +1 -0
- package/v3/dist/validation/validation-result-aggregator.js +630 -0
- package/v3/dist/validation/validation-result-aggregator.js.map +1 -0
- package/v3/package.json +1 -1
|
@@ -1,1658 +1,1664 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: a11y-ally
|
|
3
|
-
description: "Comprehensive WCAG accessibility auditing with multi-tool testing (axe-core + pa11y + Lighthouse), TRUE PARALLEL execution with Promise.allSettled, graceful degradation, retry with backoff, context-aware remediation, learning integration, and video accessibility. Uses 3-tier browser cascade: Vibium → agent-browser → Playwright+Stealth."
|
|
4
|
-
category: specialized-testing
|
|
5
|
-
priority: critical
|
|
6
|
-
tokenEstimate: 10000
|
|
7
|
-
agents: []
|
|
8
|
-
implementation_status: active
|
|
9
|
-
optimization_version: 7.0
|
|
10
|
-
last_optimized: 2026-01-26
|
|
11
|
-
dependencies: [playwright, playwright-extra, puppeteer-extra-plugin-stealth, "@axe-core/playwright", pa11y, lighthouse]
|
|
12
|
-
quick_reference_card: true
|
|
13
|
-
tags: [accessibility, wcag, a11y, video, captions, audiodesc, vtt, eu-compliance, context-aware, remediation, axe-core, pa11y, lighthouse, parallel, resilient, graceful-degradation, retry]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Claude:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
**
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
**
|
|
249
|
-
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
},
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
},
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
results.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
results.
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
results.
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
console.log(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
console.log('
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
console.log('\n===
|
|
625
|
-
console.log(JSON.stringify(results.
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
**
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
**
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
**
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
<!--
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
-
|
|
752
|
-
|
|
753
|
-
-
|
|
754
|
-
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
<!--
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
<!--
|
|
797
|
-
.
|
|
798
|
-
|
|
799
|
-
<!--
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
<!--
|
|
818
|
-
<h1>
|
|
819
|
-
<
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
</
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
<
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
/*
|
|
888
|
-
:focus
|
|
889
|
-
outline:
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
outline-
|
|
907
|
-
box-shadow: 0 0 0 6px rgba(
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
|
1012
|
-
|
|
1013
|
-
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
- Missing
|
|
1025
|
-
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
-
|
|
1030
|
-
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
|
1057
|
-
|
|
1058
|
-
| Add
|
|
1059
|
-
|
|
|
1060
|
-
| Add
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
|
1065
|
-
|
|
1066
|
-
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
```
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
#
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
-
|
|
1179
|
-
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
**
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
**
|
|
1225
|
-
|
|
1226
|
-
-
|
|
1227
|
-
-
|
|
1228
|
-
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
{
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
##
|
|
1298
|
-
{
|
|
1299
|
-
|
|
1300
|
-
##
|
|
1301
|
-
{
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
###
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
###
|
|
1317
|
-
{For EACH
|
|
1318
|
-
|
|
1319
|
-
###
|
|
1320
|
-
{
|
|
1321
|
-
|
|
1322
|
-
###
|
|
1323
|
-
{For EACH:
|
|
1324
|
-
|
|
1325
|
-
###
|
|
1326
|
-
{
|
|
1327
|
-
|
|
1328
|
-
###
|
|
1329
|
-
{
|
|
1330
|
-
|
|
1331
|
-
###
|
|
1332
|
-
{
|
|
1333
|
-
|
|
1334
|
-
###
|
|
1335
|
-
{
|
|
1336
|
-
|
|
1337
|
-
###
|
|
1338
|
-
{
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
//
|
|
1370
|
-
mcp__claude-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
|
1426
|
-
|
|
1427
|
-
|
|
|
1428
|
-
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
-
|
|
1459
|
-
-
|
|
1460
|
-
-
|
|
1461
|
-
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
-
|
|
1479
|
-
-
|
|
1480
|
-
-
|
|
1481
|
-
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
-
|
|
1499
|
-
-
|
|
1500
|
-
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
|
1512
|
-
|
|
1513
|
-
|
|
|
1514
|
-
|
|
|
1515
|
-
|
|
|
1516
|
-
|
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
- [ ]
|
|
1534
|
-
- [ ]
|
|
1535
|
-
- [ ]
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
- [ ]
|
|
1540
|
-
- [ ]
|
|
1541
|
-
- [ ]
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
- [ ]
|
|
1545
|
-
- [ ]
|
|
1546
|
-
- [ ]
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
- [ ]
|
|
1550
|
-
- [ ]
|
|
1551
|
-
- [ ]
|
|
1552
|
-
- [ ]
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
- [ ]
|
|
1556
|
-
- [ ]
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
- [ ] audit-summary.md with
|
|
1562
|
-
- [ ]
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
- [ ]
|
|
1569
|
-
- [ ]
|
|
1570
|
-
- [ ]
|
|
1571
|
-
- [ ]
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
|
1617
|
-
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1
|
+
---
|
|
2
|
+
name: a11y-ally
|
|
3
|
+
description: "Comprehensive WCAG accessibility auditing with multi-tool testing (axe-core + pa11y + Lighthouse), TRUE PARALLEL execution with Promise.allSettled, graceful degradation, retry with backoff, context-aware remediation, learning integration, and video accessibility. Uses 3-tier browser cascade: Vibium → agent-browser → Playwright+Stealth."
|
|
4
|
+
category: specialized-testing
|
|
5
|
+
priority: critical
|
|
6
|
+
tokenEstimate: 10000
|
|
7
|
+
agents: []
|
|
8
|
+
implementation_status: active
|
|
9
|
+
optimization_version: 7.0
|
|
10
|
+
last_optimized: 2026-01-26
|
|
11
|
+
dependencies: [playwright, playwright-extra, puppeteer-extra-plugin-stealth, "@axe-core/playwright", pa11y, lighthouse]
|
|
12
|
+
quick_reference_card: true
|
|
13
|
+
tags: [accessibility, wcag, a11y, video, captions, audiodesc, vtt, eu-compliance, context-aware, remediation, axe-core, pa11y, lighthouse, parallel, resilient, graceful-degradation, retry]
|
|
14
|
+
trust_tier: 3
|
|
15
|
+
validation:
|
|
16
|
+
schema_path: schemas/output.json
|
|
17
|
+
validator_path: scripts/validate.sh
|
|
18
|
+
eval_path: evals/a11y-ally.yaml
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# /a11y-ally - Comprehensive Accessibility Audit
|
|
23
|
+
|
|
24
|
+
<default_to_action>
|
|
25
|
+
When this skill is invoked with a URL, Claude executes ALL steps automatically without waiting for user prompts between steps.
|
|
26
|
+
|
|
27
|
+
## THIS IS AN LLM-POWERED SKILL
|
|
28
|
+
|
|
29
|
+
The value of this skill is **Claude's intelligence**, not just running automated tools:
|
|
30
|
+
|
|
31
|
+
| Automated Tools Do | Claude (This Skill) Does |
|
|
32
|
+
|--------------------|--------------------------|
|
|
33
|
+
| Flag "button has no name" | Analyze context: icon class, parent element, nearby text → generate "Add to wishlist" |
|
|
34
|
+
| Flag "image missing alt" | Use Vision to see the image → describe actual content |
|
|
35
|
+
| Flag "video has no captions" | Download video, extract frames, analyze each frame with Vision → generate real captions |
|
|
36
|
+
| Output generic templates | Generate context-specific, copy-paste ready fixes |
|
|
37
|
+
|
|
38
|
+
**IF YOU SKIP THE LLM ANALYSIS, THIS SKILL HAS NO VALUE.**
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## EXECUTION MODEL
|
|
43
|
+
|
|
44
|
+
**CLAUDE EXECUTES ALL STEPS WITHOUT STOPPING.**
|
|
45
|
+
|
|
46
|
+
Do NOT wait for user prompts between steps. Execute the full pipeline:
|
|
47
|
+
|
|
48
|
+
1. **Data Collection**: Run multi-tool scan (axe-core, pa11y, Lighthouse) via Bash
|
|
49
|
+
2. **LLM Analysis**: Read results and analyze context for each violation
|
|
50
|
+
3. **Vision Pipeline**: If videos detected → download → extract frames → Read each frame → describe
|
|
51
|
+
4. **Intelligent Remediation**: Generate context-specific fixes using your reasoning
|
|
52
|
+
5. **Generate Reports**: Write all output files to `docs/accessibility-scans/{page-slug}/`
|
|
53
|
+
|
|
54
|
+
**WRONG:**
|
|
55
|
+
```
|
|
56
|
+
Claude: "I found 5 violations. Should I analyze them?"
|
|
57
|
+
User: "Yes"
|
|
58
|
+
Claude: "I see a video. Should I run the video pipeline?"
|
|
59
|
+
User: "Yes"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**RIGHT:**
|
|
63
|
+
```
|
|
64
|
+
Claude: [Runs scan] → [Analyzes violations] → [Downloads video] → [Extracts frames] →
|
|
65
|
+
[Reads each frame with Vision] → [Generates captions] → [Writes all files]
|
|
66
|
+
"Audit complete. Generated 4 files in docs/accessibility-scans/example/"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## STEP 1: BROWSER AUTOMATION - Content Fetching
|
|
72
|
+
|
|
73
|
+
### 1.1: Try VIBIUM First (Primary)
|
|
74
|
+
```javascript
|
|
75
|
+
ToolSearch("select:mcp__vibium__browser_launch")
|
|
76
|
+
ToolSearch("select:mcp__vibium__browser_navigate")
|
|
77
|
+
mcp__vibium__browser_launch({ headless: true })
|
|
78
|
+
mcp__vibium__browser_navigate({ url: "TARGET_URL" })
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**If Vibium fails** → Go to STEP 1b
|
|
82
|
+
|
|
83
|
+
### 1b: Try AGENT-BROWSER Fallback
|
|
84
|
+
```javascript
|
|
85
|
+
ToolSearch("select:mcp__claude-flow_alpha__browser_open")
|
|
86
|
+
mcp__claude-flow_alpha__browser_open({ url: "TARGET_URL", waitUntil: "networkidle" })
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**If agent-browser fails** → Go to STEP 1c
|
|
90
|
+
|
|
91
|
+
### 1c: PLAYWRIGHT + STEALTH (Final Fallback)
|
|
92
|
+
```bash
|
|
93
|
+
mkdir -p /tmp/a11y-work && cd /tmp/a11y-work
|
|
94
|
+
npm init -y 2>/dev/null
|
|
95
|
+
npm install playwright-extra puppeteer-extra-plugin-stealth @axe-core/playwright pa11y lighthouse chrome-launcher 2>/dev/null
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Create and run scan script - see STEP 2 for full multi-tool scan code.
|
|
99
|
+
|
|
100
|
+
### 1d: PARALLEL MULTI-PAGE AUDIT (Optional)
|
|
101
|
+
|
|
102
|
+
For auditing multiple URLs simultaneously, use parallel execution:
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// /tmp/a11y-work/parallel-audit.js
|
|
106
|
+
const { chromium } = require('playwright-extra');
|
|
107
|
+
const stealth = require('puppeteer-extra-plugin-stealth')();
|
|
108
|
+
const { AxeBuilder } = require('@axe-core/playwright');
|
|
109
|
+
|
|
110
|
+
chromium.use(stealth);
|
|
111
|
+
|
|
112
|
+
const MAX_CONCURRENT = 6; // Maximum parallel auditors
|
|
113
|
+
|
|
114
|
+
async function auditUrl(browser, url) {
|
|
115
|
+
const context = await browser.newContext();
|
|
116
|
+
const page = await context.newPage();
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
120
|
+
await page.waitForTimeout(2000);
|
|
121
|
+
|
|
122
|
+
const axeResults = await new AxeBuilder({ page })
|
|
123
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
|
|
124
|
+
.analyze();
|
|
125
|
+
|
|
126
|
+
return { url, success: true, violations: axeResults.violations };
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return { url, success: false, error: error.message };
|
|
129
|
+
} finally {
|
|
130
|
+
await context.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function parallelAudit(urls) {
|
|
135
|
+
const browser = await chromium.launch({ headless: true });
|
|
136
|
+
const results = [];
|
|
137
|
+
|
|
138
|
+
// Process in chunks of MAX_CONCURRENT
|
|
139
|
+
for (let i = 0; i < urls.length; i += MAX_CONCURRENT) {
|
|
140
|
+
const chunk = urls.slice(i, i + MAX_CONCURRENT);
|
|
141
|
+
console.log(`Auditing batch ${Math.floor(i/MAX_CONCURRENT) + 1}: ${chunk.length} URLs`);
|
|
142
|
+
|
|
143
|
+
const chunkResults = await Promise.all(
|
|
144
|
+
chunk.map(url => auditUrl(browser, url))
|
|
145
|
+
);
|
|
146
|
+
results.push(...chunkResults);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
await browser.close();
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Usage: node parallel-audit.js url1 url2 url3 ...
|
|
154
|
+
const urls = process.argv.slice(2);
|
|
155
|
+
if (urls.length > 0) {
|
|
156
|
+
parallelAudit(urls).then(results => {
|
|
157
|
+
console.log(JSON.stringify(results, null, 2));
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Usage for multi-page audit:**
|
|
163
|
+
```bash
|
|
164
|
+
node parallel-audit.js https://example.com https://example.com/about https://example.com/contact
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 1e: SITE CRAWL MODE (Optional)
|
|
168
|
+
|
|
169
|
+
For comprehensive site audits, crawl and audit all pages:
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// /tmp/a11y-work/crawl-audit.js
|
|
173
|
+
async function crawlAndAudit(startUrl, maxPages = 50) {
|
|
174
|
+
const browser = await chromium.launch({ headless: true });
|
|
175
|
+
const visited = new Set();
|
|
176
|
+
const toVisit = [startUrl];
|
|
177
|
+
const results = [];
|
|
178
|
+
const baseUrl = new URL(startUrl).origin;
|
|
179
|
+
|
|
180
|
+
while (toVisit.length > 0 && results.length < maxPages) {
|
|
181
|
+
const url = toVisit.shift();
|
|
182
|
+
if (visited.has(url)) continue;
|
|
183
|
+
visited.add(url);
|
|
184
|
+
|
|
185
|
+
console.log(`[${results.length + 1}/${maxPages}] Auditing: ${url}`);
|
|
186
|
+
|
|
187
|
+
const context = await browser.newContext();
|
|
188
|
+
const page = await context.newPage();
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
192
|
+
|
|
193
|
+
// Extract same-domain links for crawling
|
|
194
|
+
const links = await page.evaluate((base) => {
|
|
195
|
+
return [...document.querySelectorAll('a[href]')]
|
|
196
|
+
.map(a => a.href)
|
|
197
|
+
.filter(href => href.startsWith(base) && !href.includes('#'))
|
|
198
|
+
.filter(href => !href.match(/\.(pdf|jpg|png|gif|css|js)$/i));
|
|
199
|
+
}, baseUrl);
|
|
200
|
+
|
|
201
|
+
// Add new links to queue
|
|
202
|
+
links.forEach(link => {
|
|
203
|
+
if (!visited.has(link) && !toVisit.includes(link)) {
|
|
204
|
+
toVisit.push(link);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Run accessibility audit
|
|
209
|
+
const axeResults = await new AxeBuilder({ page })
|
|
210
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
|
|
211
|
+
.analyze();
|
|
212
|
+
|
|
213
|
+
results.push({ url, violations: axeResults.violations });
|
|
214
|
+
} catch (e) {
|
|
215
|
+
results.push({ url, error: e.message });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
await context.close();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
await browser.close();
|
|
222
|
+
return { pagesAudited: results.length, results };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Usage: node crawl-audit.js https://example.com 50
|
|
226
|
+
const [startUrl, maxPages] = process.argv.slice(2);
|
|
227
|
+
crawlAndAudit(startUrl, parseInt(maxPages) || 50).then(r => console.log(JSON.stringify(r, null, 2)));
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## STEP 2: COMPREHENSIVE WCAG SCAN (Multi-Tool, Parallel, Resilient)
|
|
233
|
+
|
|
234
|
+
**IMPORTANT:** This step uses THREE accessibility testing tools for maximum coverage:
|
|
235
|
+
- **axe-core**: Industry standard, excellent for ARIA and semantic issues
|
|
236
|
+
- **pa11y**: Strong on contrast, links, and HTML validation
|
|
237
|
+
- **Lighthouse**: Google's accessibility scoring with performance correlation
|
|
238
|
+
|
|
239
|
+
Combined detection rate is ~15% higher than any single tool.
|
|
240
|
+
|
|
241
|
+
### 2.0: RESILIENCE ARCHITECTURE (v7.0 Enhancement)
|
|
242
|
+
|
|
243
|
+
**Key improvements over v6.0:**
|
|
244
|
+
|
|
245
|
+
| Feature | v6.0 (Old) | v7.0 (New) |
|
|
246
|
+
|---------|------------|------------|
|
|
247
|
+
| Tool execution | Sequential | **Parallel (Promise.allSettled)** |
|
|
248
|
+
| Timeout handling | Global 60s | **Per-tool (60s/60s/90s)** |
|
|
249
|
+
| Failure mode | All-or-nothing | **Graceful degradation** |
|
|
250
|
+
| Retry logic | None | **Exponential backoff (3 retries)** |
|
|
251
|
+
| Output style | Wait for all | **Progressive (stream as ready)** |
|
|
252
|
+
| Minimum tools | 3 required | **1 of 3 sufficient** |
|
|
253
|
+
|
|
254
|
+
**Coverage by tools succeeded:**
|
|
255
|
+
- 3/3 tools: ~95% detection (optimal)
|
|
256
|
+
- 2/3 tools: ~85% detection (good)
|
|
257
|
+
- 1/3 tools: ~70% detection (acceptable)
|
|
258
|
+
- 0/3 tools: FAIL - retry with different strategy
|
|
259
|
+
|
|
260
|
+
### 2.1: Run Multi-Tool Analysis (PARALLEL + RESILIENT)
|
|
261
|
+
Create and run `/tmp/a11y-work/multi-tool-scan.js`:
|
|
262
|
+
```javascript
|
|
263
|
+
const { chromium } = require('playwright-extra');
|
|
264
|
+
const stealth = require('puppeteer-extra-plugin-stealth')();
|
|
265
|
+
const { AxeBuilder } = require('@axe-core/playwright');
|
|
266
|
+
const pa11y = require('pa11y');
|
|
267
|
+
const lighthouse = require('lighthouse').default || require('lighthouse');
|
|
268
|
+
const { launch: launchChrome } = require('chrome-launcher');
|
|
269
|
+
const fs = require('fs');
|
|
270
|
+
|
|
271
|
+
chromium.use(stealth);
|
|
272
|
+
|
|
273
|
+
const TARGET_URL = process.argv[2] || 'TARGET_URL';
|
|
274
|
+
const OUTPUT_FILE = '/tmp/a11y-work/scan-results.json';
|
|
275
|
+
const SYSTEM_CHROMIUM = '/usr/bin/chromium';
|
|
276
|
+
|
|
277
|
+
// ========== RESILIENCE UTILITIES ==========
|
|
278
|
+
|
|
279
|
+
// Timeout wrapper - wraps any promise with a timeout
|
|
280
|
+
function withTimeout(promise, ms, name) {
|
|
281
|
+
return Promise.race([
|
|
282
|
+
promise,
|
|
283
|
+
new Promise((_, reject) =>
|
|
284
|
+
setTimeout(() => reject(new Error(`${name} timed out after ${ms}ms`)), ms)
|
|
285
|
+
)
|
|
286
|
+
]);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Retry wrapper - retries with exponential backoff
|
|
290
|
+
async function withRetry(fn, name, maxRetries = 3, baseDelay = 2000) {
|
|
291
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
292
|
+
try {
|
|
293
|
+
return await fn();
|
|
294
|
+
} catch (error) {
|
|
295
|
+
const isLastAttempt = attempt === maxRetries;
|
|
296
|
+
console.log(`[${name}] Attempt ${attempt}/${maxRetries} failed: ${error.message}`);
|
|
297
|
+
if (isLastAttempt) throw error;
|
|
298
|
+
const delay = baseDelay * Math.pow(2, attempt - 1); // Exponential backoff
|
|
299
|
+
console.log(`[${name}] Retrying in ${delay}ms...`);
|
|
300
|
+
await new Promise(r => setTimeout(r, delay));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Sleep utility
|
|
306
|
+
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
307
|
+
|
|
308
|
+
// Progressive output - append results as they arrive
|
|
309
|
+
function progressiveOutput(tool, data) {
|
|
310
|
+
console.log(`\n=== ${tool.toUpperCase()} COMPLETE ===`);
|
|
311
|
+
console.log(JSON.stringify(data, null, 2));
|
|
312
|
+
|
|
313
|
+
// Append to results file for progressive access
|
|
314
|
+
try {
|
|
315
|
+
let results = {};
|
|
316
|
+
if (fs.existsSync(OUTPUT_FILE)) {
|
|
317
|
+
results = JSON.parse(fs.readFileSync(OUTPUT_FILE, 'utf8'));
|
|
318
|
+
}
|
|
319
|
+
results[tool] = data;
|
|
320
|
+
results.lastUpdated = new Date().toISOString();
|
|
321
|
+
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(results, null, 2));
|
|
322
|
+
} catch (e) { /* ignore file errors */ }
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ========== TOOL RUNNERS ==========
|
|
326
|
+
|
|
327
|
+
// TOOL 1: Axe-core (with page info extraction)
|
|
328
|
+
async function runAxeCore(url) {
|
|
329
|
+
console.log('[axe-core] Starting...');
|
|
330
|
+
const browser = await chromium.launch({
|
|
331
|
+
headless: true,
|
|
332
|
+
executablePath: SYSTEM_CHROMIUM,
|
|
333
|
+
args: [
|
|
334
|
+
'--no-sandbox',
|
|
335
|
+
'--disable-setuid-sandbox',
|
|
336
|
+
'--disable-dev-shm-usage',
|
|
337
|
+
'--disable-blink-features=AutomationControlled'
|
|
338
|
+
]
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const context = await browser.newContext({
|
|
342
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
343
|
+
locale: 'en-US',
|
|
344
|
+
viewport: { width: 1920, height: 1080 }
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
const page = await context.newPage();
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
// Use domcontentloaded (faster, more reliable than networkidle)
|
|
351
|
+
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
352
|
+
|
|
353
|
+
// Random delay to appear human
|
|
354
|
+
await sleep(2000 + Math.random() * 2000);
|
|
355
|
+
|
|
356
|
+
// Try to dismiss cookie banners
|
|
357
|
+
try {
|
|
358
|
+
const cookieSelectors = [
|
|
359
|
+
'button:has-text("Accept")', 'button:has-text("Akzeptieren")',
|
|
360
|
+
'button:has-text("Alle akzeptieren")', '[data-testid="cookie-accept"]',
|
|
361
|
+
'#onetrust-accept-btn-handler', '.cookie-consent-accept'
|
|
362
|
+
];
|
|
363
|
+
for (const selector of cookieSelectors) {
|
|
364
|
+
const btn = await page.$(selector);
|
|
365
|
+
if (btn) { await btn.click(); await sleep(500); break; }
|
|
366
|
+
}
|
|
367
|
+
} catch (e) { /* ignore cookie errors */ }
|
|
368
|
+
|
|
369
|
+
// Run axe-core analysis
|
|
370
|
+
const axeResults = await new AxeBuilder({ page })
|
|
371
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
|
|
372
|
+
.analyze();
|
|
373
|
+
|
|
374
|
+
// Extract comprehensive page info
|
|
375
|
+
const pageInfo = await page.evaluate(() => ({
|
|
376
|
+
title: document.title,
|
|
377
|
+
url: window.location.href,
|
|
378
|
+
lang: document.documentElement.lang,
|
|
379
|
+
images: {
|
|
380
|
+
total: document.querySelectorAll('img').length,
|
|
381
|
+
withAlt: document.querySelectorAll('img[alt]').length,
|
|
382
|
+
withoutAlt: document.querySelectorAll('img:not([alt])').length,
|
|
383
|
+
emptyAlt: document.querySelectorAll('img[alt=""]').length
|
|
384
|
+
},
|
|
385
|
+
headings: {
|
|
386
|
+
h1: Array.from(document.querySelectorAll('h1')).map(h => h.textContent.trim().slice(0,60)),
|
|
387
|
+
h2: document.querySelectorAll('h2').length,
|
|
388
|
+
h3: document.querySelectorAll('h3').length,
|
|
389
|
+
total: document.querySelectorAll('h1,h2,h3,h4,h5,h6').length
|
|
390
|
+
},
|
|
391
|
+
forms: {
|
|
392
|
+
total: document.querySelectorAll('form').length,
|
|
393
|
+
inputs: document.querySelectorAll('input, select, textarea').length,
|
|
394
|
+
buttons: document.querySelectorAll('button').length
|
|
395
|
+
},
|
|
396
|
+
links: { total: document.querySelectorAll('a').length },
|
|
397
|
+
aria: {
|
|
398
|
+
ariaLabels: document.querySelectorAll('[aria-label]').length,
|
|
399
|
+
roles: document.querySelectorAll('[role]').length
|
|
400
|
+
},
|
|
401
|
+
landmarks: {
|
|
402
|
+
main: document.querySelectorAll('main').length,
|
|
403
|
+
nav: document.querySelectorAll('nav').length,
|
|
404
|
+
header: document.querySelectorAll('header').length,
|
|
405
|
+
footer: document.querySelectorAll('footer').length
|
|
406
|
+
},
|
|
407
|
+
media: {
|
|
408
|
+
videos: document.querySelectorAll('video').length,
|
|
409
|
+
iframes: document.querySelectorAll('iframe').length,
|
|
410
|
+
videoUrls: Array.from(document.querySelectorAll('video')).map(v => {
|
|
411
|
+
const src = v.src || (v.querySelector('source') ? v.querySelector('source').src : '');
|
|
412
|
+
return {
|
|
413
|
+
src: src,
|
|
414
|
+
hasCaptions: !!v.querySelector('track[kind="captions"]')
|
|
415
|
+
};
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
}));
|
|
419
|
+
|
|
420
|
+
const violations = axeResults.violations.map(v => ({
|
|
421
|
+
tool: 'axe-core',
|
|
422
|
+
id: v.id,
|
|
423
|
+
impact: v.impact,
|
|
424
|
+
description: v.description,
|
|
425
|
+
help: v.help,
|
|
426
|
+
helpUrl: v.helpUrl,
|
|
427
|
+
tags: v.tags,
|
|
428
|
+
nodeCount: v.nodes.length,
|
|
429
|
+
nodes: v.nodes.slice(0, 5).map(n => ({
|
|
430
|
+
html: n.html.slice(0, 200),
|
|
431
|
+
target: n.target,
|
|
432
|
+
failureSummary: n.failureSummary
|
|
433
|
+
}))
|
|
434
|
+
}));
|
|
435
|
+
|
|
436
|
+
return {
|
|
437
|
+
success: true,
|
|
438
|
+
pageInfo,
|
|
439
|
+
violations,
|
|
440
|
+
passesCount: axeResults.passes.length
|
|
441
|
+
};
|
|
442
|
+
} finally {
|
|
443
|
+
await context.close();
|
|
444
|
+
await browser.close();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// TOOL 2: Pa11y
|
|
449
|
+
async function runPa11y(url) {
|
|
450
|
+
console.log('[pa11y] Starting...');
|
|
451
|
+
const results = await pa11y(url, {
|
|
452
|
+
standard: 'WCAG2AA',
|
|
453
|
+
timeout: 45000,
|
|
454
|
+
wait: 2000,
|
|
455
|
+
chromeLaunchConfig: {
|
|
456
|
+
executablePath: SYSTEM_CHROMIUM,
|
|
457
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
const violations = results.issues.map(issue => ({
|
|
462
|
+
tool: 'pa11y',
|
|
463
|
+
id: issue.code,
|
|
464
|
+
impact: issue.type === 'error' ? 'serious' : issue.type === 'warning' ? 'moderate' : 'minor',
|
|
465
|
+
description: issue.message,
|
|
466
|
+
selector: issue.selector,
|
|
467
|
+
context: (issue.context || '').slice(0, 200)
|
|
468
|
+
}));
|
|
469
|
+
|
|
470
|
+
return { success: true, violations, total: results.issues.length };
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// TOOL 3: Lighthouse
|
|
474
|
+
async function runLighthouse(url) {
|
|
475
|
+
console.log('[lighthouse] Starting...');
|
|
476
|
+
const chrome = await launchChrome({
|
|
477
|
+
chromePath: SYSTEM_CHROMIUM,
|
|
478
|
+
chromeFlags: ['--headless', '--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage']
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
try {
|
|
482
|
+
const result = await lighthouse(url, {
|
|
483
|
+
port: chrome.port,
|
|
484
|
+
onlyCategories: ['accessibility'],
|
|
485
|
+
output: 'json'
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
const lhr = result.lhr;
|
|
489
|
+
const score = Math.round(lhr.categories.accessibility.score * 100);
|
|
490
|
+
const violations = Object.values(lhr.audits)
|
|
491
|
+
.filter(audit => audit.score !== null && audit.score < 1)
|
|
492
|
+
.map(audit => ({
|
|
493
|
+
tool: 'lighthouse',
|
|
494
|
+
id: audit.id,
|
|
495
|
+
impact: audit.score === 0 ? 'critical' : audit.score < 0.5 ? 'serious' : 'moderate',
|
|
496
|
+
score: audit.score,
|
|
497
|
+
description: audit.title
|
|
498
|
+
}));
|
|
499
|
+
|
|
500
|
+
return { success: true, score, violations };
|
|
501
|
+
} finally {
|
|
502
|
+
await chrome.kill();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// ========== MAIN: PARALLEL EXECUTION WITH GRACEFUL DEGRADATION ==========
|
|
507
|
+
|
|
508
|
+
(async () => {
|
|
509
|
+
console.log('=== MULTI-TOOL ACCESSIBILITY SCAN (v7.0 PARALLEL + RESILIENT) ===');
|
|
510
|
+
console.log('Target:', TARGET_URL);
|
|
511
|
+
console.log('Strategy: Promise.allSettled with per-tool timeouts\n');
|
|
512
|
+
|
|
513
|
+
const startTime = Date.now();
|
|
514
|
+
|
|
515
|
+
// Run ALL tools in PARALLEL with individual timeouts
|
|
516
|
+
const [axeResult, pa11yResult, lighthouseResult] = await Promise.allSettled([
|
|
517
|
+
withTimeout(
|
|
518
|
+
withRetry(() => runAxeCore(TARGET_URL), 'axe-core', 2, 3000),
|
|
519
|
+
60000, 'axe-core'
|
|
520
|
+
),
|
|
521
|
+
withTimeout(
|
|
522
|
+
withRetry(() => runPa11y(TARGET_URL), 'pa11y', 2, 3000),
|
|
523
|
+
60000, 'pa11y'
|
|
524
|
+
),
|
|
525
|
+
withTimeout(
|
|
526
|
+
withRetry(() => runLighthouse(TARGET_URL), 'lighthouse', 2, 3000),
|
|
527
|
+
90000, 'lighthouse'
|
|
528
|
+
)
|
|
529
|
+
]);
|
|
530
|
+
|
|
531
|
+
// ========== PROCESS RESULTS (Graceful Degradation) ==========
|
|
532
|
+
const results = {
|
|
533
|
+
url: TARGET_URL,
|
|
534
|
+
timestamp: new Date().toISOString(),
|
|
535
|
+
duration: `${((Date.now() - startTime) / 1000).toFixed(1)}s`,
|
|
536
|
+
toolsSucceeded: 0,
|
|
537
|
+
toolsFailed: 0,
|
|
538
|
+
pageInfo: null,
|
|
539
|
+
violations: [],
|
|
540
|
+
byTool: {}
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
// Process axe-core results
|
|
544
|
+
if (axeResult.status === 'fulfilled') {
|
|
545
|
+
results.toolsSucceeded++;
|
|
546
|
+
results.pageInfo = axeResult.value.pageInfo;
|
|
547
|
+
results.violations.push(...axeResult.value.violations);
|
|
548
|
+
results.byTool['axe-core'] = {
|
|
549
|
+
success: true,
|
|
550
|
+
count: axeResult.value.violations.length,
|
|
551
|
+
passes: axeResult.value.passesCount
|
|
552
|
+
};
|
|
553
|
+
progressiveOutput('axe-core', axeResult.value);
|
|
554
|
+
} else {
|
|
555
|
+
results.toolsFailed++;
|
|
556
|
+
results.byTool['axe-core'] = { success: false, error: axeResult.reason.message };
|
|
557
|
+
console.log('\n[axe-core] FAILED:', axeResult.reason.message);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Process pa11y results
|
|
561
|
+
if (pa11yResult.status === 'fulfilled') {
|
|
562
|
+
results.toolsSucceeded++;
|
|
563
|
+
results.violations.push(...pa11yResult.value.violations);
|
|
564
|
+
results.byTool['pa11y'] = {
|
|
565
|
+
success: true,
|
|
566
|
+
count: pa11yResult.value.violations.length
|
|
567
|
+
};
|
|
568
|
+
progressiveOutput('pa11y', pa11yResult.value);
|
|
569
|
+
} else {
|
|
570
|
+
results.toolsFailed++;
|
|
571
|
+
results.byTool['pa11y'] = { success: false, error: pa11yResult.reason.message };
|
|
572
|
+
console.log('\n[pa11y] FAILED:', pa11yResult.reason.message);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Process lighthouse results
|
|
576
|
+
if (lighthouseResult.status === 'fulfilled') {
|
|
577
|
+
results.toolsSucceeded++;
|
|
578
|
+
results.violations.push(...lighthouseResult.value.violations);
|
|
579
|
+
results.byTool['lighthouse'] = {
|
|
580
|
+
success: true,
|
|
581
|
+
score: lighthouseResult.value.score,
|
|
582
|
+
count: lighthouseResult.value.violations.length
|
|
583
|
+
};
|
|
584
|
+
progressiveOutput('lighthouse', lighthouseResult.value);
|
|
585
|
+
} else {
|
|
586
|
+
results.toolsFailed++;
|
|
587
|
+
results.byTool['lighthouse'] = { success: false, error: lighthouseResult.reason.message };
|
|
588
|
+
console.log('\n[lighthouse] FAILED:', lighthouseResult.reason.message);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// ========== DEDUPLICATE VIOLATIONS ==========
|
|
592
|
+
const seen = new Set();
|
|
593
|
+
const uniqueViolations = [];
|
|
594
|
+
for (const v of results.violations) {
|
|
595
|
+
const key = (v.description || '').toLowerCase().slice(0, 50);
|
|
596
|
+
if (!seen.has(key)) {
|
|
597
|
+
seen.add(key);
|
|
598
|
+
uniqueViolations.push(v);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
results.uniqueViolations = uniqueViolations;
|
|
602
|
+
results.totalUnique = uniqueViolations.length;
|
|
603
|
+
|
|
604
|
+
// ========== FINAL OUTPUT ==========
|
|
605
|
+
console.log('\n' + '='.repeat(60));
|
|
606
|
+
console.log('=== SCAN COMPLETE ===');
|
|
607
|
+
console.log('='.repeat(60));
|
|
608
|
+
console.log(`Tools succeeded: ${results.toolsSucceeded}/3`);
|
|
609
|
+
console.log(`Tools failed: ${results.toolsFailed}/3`);
|
|
610
|
+
console.log(`Duration: ${results.duration}`);
|
|
611
|
+
console.log(`Total unique violations: ${results.totalUnique}`);
|
|
612
|
+
|
|
613
|
+
if (results.toolsSucceeded === 0) {
|
|
614
|
+
console.log('\n⚠️ ALL TOOLS FAILED - Consider:');
|
|
615
|
+
console.log(' 1. Site may have strong bot protection');
|
|
616
|
+
console.log(' 2. Try Vibium MCP browser instead');
|
|
617
|
+
console.log(' 3. Check network connectivity');
|
|
618
|
+
} else if (results.toolsSucceeded < 3) {
|
|
619
|
+
console.log(`\n⚠️ Partial coverage (${results.toolsSucceeded}/3 tools) - Results still usable`);
|
|
620
|
+
} else {
|
|
621
|
+
console.log('\n✅ Full coverage achieved (3/3 tools)');
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
console.log('\n=== PAGE INFO ===');
|
|
625
|
+
console.log(JSON.stringify(results.pageInfo, null, 2));
|
|
626
|
+
|
|
627
|
+
console.log('\n=== VIOLATIONS BY TOOL ===');
|
|
628
|
+
console.log(JSON.stringify(results.byTool, null, 2));
|
|
629
|
+
|
|
630
|
+
console.log('\n=== UNIQUE VIOLATIONS ===');
|
|
631
|
+
console.log(JSON.stringify(results.uniqueViolations, null, 2));
|
|
632
|
+
|
|
633
|
+
// Save final results
|
|
634
|
+
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(results, null, 2));
|
|
635
|
+
console.log(`\nResults saved to: ${OUTPUT_FILE}`);
|
|
636
|
+
})();
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### 2.2: Read Scan Results
|
|
640
|
+
|
|
641
|
+
After running the scan, read the results file:
|
|
642
|
+
```bash
|
|
643
|
+
cat /tmp/a11y-work/scan-results.json
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
The results include:
|
|
647
|
+
- **pageInfo**: Page structure, images, headings, media
|
|
648
|
+
- **violations**: All violations from all tools (deduplicated)
|
|
649
|
+
- **byTool**: Success/failure status per tool
|
|
650
|
+
- **toolsSucceeded**: Number of tools that completed (1-3)
|
|
651
|
+
|
|
652
|
+
### 2.3: Graceful Degradation Decision Tree
|
|
653
|
+
|
|
654
|
+
| Tools Succeeded | Action |
|
|
655
|
+
|-----------------|--------|
|
|
656
|
+
| **3/3** | ✅ Full coverage - proceed with all results |
|
|
657
|
+
| **2/3** | ⚠️ Good coverage - note which tool failed in report |
|
|
658
|
+
| **1/3** | ⚠️ Basic coverage - proceed but flag limited confidence |
|
|
659
|
+
| **0/3** | ❌ Retry with Vibium MCP, or document failure |
|
|
660
|
+
|
|
661
|
+
### 2.4: MANDATORY - Check for Videos and Trigger Pipeline
|
|
662
|
+
|
|
663
|
+
After reading scan results, check `pageInfo.media.videoUrls`:
|
|
664
|
+
|
|
665
|
+
```javascript
|
|
666
|
+
// Check scan-results.json for videos
|
|
667
|
+
const results = JSON.parse(fs.readFileSync('/tmp/a11y-work/scan-results.json'));
|
|
668
|
+
if (results.pageInfo && results.pageInfo.media.videoUrls.length > 0) {
|
|
669
|
+
console.log('=== VIDEOS DETECTED - TRIGGERING VIDEO PIPELINE ===');
|
|
670
|
+
for (const video of results.pageInfo.media.videoUrls) {
|
|
671
|
+
console.log(`Video: ${video.src}`);
|
|
672
|
+
console.log(` Has captions: ${video.hasCaptions}`);
|
|
673
|
+
}
|
|
674
|
+
// PROCEED TO STEP 7 IMMEDIATELY
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**IF videos detected AND hasCaptions=false → STEP 7 is MANDATORY before generating reports.**
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## STEP 3: CONTEXT-AWARE REMEDIATION (LLM-POWERED)
|
|
683
|
+
|
|
684
|
+
**THIS IS WHERE CLAUDE'S INTELLIGENCE MATTERS.**
|
|
685
|
+
|
|
686
|
+
Generic tools output: `aria-label="[DESCRIPTION]"`
|
|
687
|
+
You output: `aria-label="Add to shopping cart"` because you understand context.
|
|
688
|
+
|
|
689
|
+
### 3.1: Context Analysis (Use Your Reasoning)
|
|
690
|
+
|
|
691
|
+
For EACH violation, Claude must:
|
|
692
|
+
|
|
693
|
+
1. **READ THE HTML CONTEXT** - Don't just see `<button class="btn">`, see:
|
|
694
|
+
```html
|
|
695
|
+
<div class="product-card" data-product="Adidas Superstar">
|
|
696
|
+
<img src="superstar.jpg" alt="White sneakers">
|
|
697
|
+
<span class="price">$99</span>
|
|
698
|
+
<button class="btn add-to-cart"> <!-- THIS IS THE VIOLATION -->
|
|
699
|
+
<svg class="icon-cart">...</svg>
|
|
700
|
+
</button>
|
|
701
|
+
</div>
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
2. **INFER PURPOSE** from:
|
|
705
|
+
- Class names: `add-to-cart`, `wishlist`, `menu-toggle`
|
|
706
|
+
- Parent context: Inside `.product-card` with product data
|
|
707
|
+
- Icon classes: `icon-cart`, `icon-heart`, `icon-search`
|
|
708
|
+
- Nearby text: Product name, price, "Add to bag"
|
|
709
|
+
- Page section: Header nav vs product grid vs checkout
|
|
710
|
+
|
|
711
|
+
3. **GENERATE SPECIFIC FIX**:
|
|
712
|
+
```html
|
|
713
|
+
<!-- NOT THIS (generic template) -->
|
|
714
|
+
<button aria-label="[DESCRIPTION]">
|
|
715
|
+
|
|
716
|
+
<!-- THIS (context-aware) -->
|
|
717
|
+
<button aria-label="Add Adidas Superstar to cart - $99">
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
### 3.2: Confidence Scoring
|
|
721
|
+
|
|
722
|
+
Rate your confidence in each fix:
|
|
723
|
+
- **0.9+**: Clear context (class="add-to-cart" near product name)
|
|
724
|
+
- **0.7-0.9**: Reasonable inference (icon-cart class alone)
|
|
725
|
+
- **<0.7**: Needs human review (ambiguous context)
|
|
726
|
+
|
|
727
|
+
Include confidence in remediation.md:
|
|
728
|
+
```markdown
|
|
729
|
+
### Button: `.product-card .btn` (Confidence: 0.95)
|
|
730
|
+
**Context:** Inside product card for "Adidas Superstar", has cart icon
|
|
731
|
+
**Fix:** `aria-label="Add Adidas Superstar to cart"`
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### 3.2: Remediation Templates by Violation Type
|
|
735
|
+
|
|
736
|
+
**Form Labels (WCAG 1.3.1, 3.3.2, 4.1.2)**
|
|
737
|
+
```html
|
|
738
|
+
<!-- Context: Input inside payment form, near "Card Number" text -->
|
|
739
|
+
<!-- Confidence: 0.95 -->
|
|
740
|
+
|
|
741
|
+
<!-- BEFORE -->
|
|
742
|
+
<input type="text" name="cardNumber" placeholder="1234 5678 9012 3456">
|
|
743
|
+
|
|
744
|
+
<!-- AFTER -->
|
|
745
|
+
<label for="card-number">Credit Card Number</label>
|
|
746
|
+
<input type="text"
|
|
747
|
+
id="card-number"
|
|
748
|
+
name="cardNumber"
|
|
749
|
+
placeholder="1234 5678 9012 3456"
|
|
750
|
+
aria-describedby="card-hint"
|
|
751
|
+
autocomplete="cc-number"
|
|
752
|
+
inputmode="numeric"
|
|
753
|
+
pattern="[0-9\s]{13,19}">
|
|
754
|
+
<span id="card-hint" class="visually-hidden">Enter 16-digit card number</span>
|
|
755
|
+
|
|
756
|
+
<!-- RATIONALE -->
|
|
757
|
+
- Visible label aids all users
|
|
758
|
+
- aria-describedby provides additional context
|
|
759
|
+
- autocomplete enables autofill
|
|
760
|
+
- inputmode shows numeric keyboard on mobile
|
|
761
|
+
- pattern enables browser validation
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
**Icon Buttons (WCAG 4.1.2)**
|
|
765
|
+
```html
|
|
766
|
+
<!-- Context: Button with SVG inside nav, classes include "menu-toggle" -->
|
|
767
|
+
<!-- Confidence: 0.92 -->
|
|
768
|
+
|
|
769
|
+
<!-- BEFORE -->
|
|
770
|
+
<button class="menu-toggle">
|
|
771
|
+
<svg>...</svg>
|
|
772
|
+
</button>
|
|
773
|
+
|
|
774
|
+
<!-- AFTER -->
|
|
775
|
+
<button class="menu-toggle"
|
|
776
|
+
type="button"
|
|
777
|
+
aria-expanded="false"
|
|
778
|
+
aria-controls="main-menu"
|
|
779
|
+
aria-label="Open navigation menu">
|
|
780
|
+
<svg aria-hidden="true" focusable="false">...</svg>
|
|
781
|
+
</button>
|
|
782
|
+
|
|
783
|
+
<!-- RATIONALE -->
|
|
784
|
+
- aria-label describes action, not icon
|
|
785
|
+
- aria-expanded communicates state
|
|
786
|
+
- aria-controls links to menu element
|
|
787
|
+
- SVG hidden from assistive tech (decorative)
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
**Color Contrast (WCAG 1.4.3)**
|
|
791
|
+
```html
|
|
792
|
+
<!-- Context: Gray text (#767676) on white background -->
|
|
793
|
+
<!-- Current ratio: 4.48:1 (FAILS AA for normal text) -->
|
|
794
|
+
<!-- Required: 4.5:1 (AA) or 7:1 (AAA) -->
|
|
795
|
+
|
|
796
|
+
<!-- BEFORE -->
|
|
797
|
+
.low-contrast { color: #767676; background: #ffffff; }
|
|
798
|
+
|
|
799
|
+
<!-- AFTER (Option 1: Darken text - minimal change) -->
|
|
800
|
+
.accessible { color: #757575; background: #ffffff; } /* 4.6:1 - PASSES AA */
|
|
801
|
+
|
|
802
|
+
<!-- AFTER (Option 2: Higher contrast for AAA) -->
|
|
803
|
+
.high-contrast { color: #595959; background: #ffffff; } /* 7.0:1 - PASSES AAA */
|
|
804
|
+
|
|
805
|
+
<!-- COLOR ALTERNATIVES -->
|
|
806
|
+
| Original | AA Pass | AAA Pass | Notes |
|
|
807
|
+
|----------|---------|----------|-------|
|
|
808
|
+
| #767676 | #757575 | #595959 | Gray text |
|
|
809
|
+
| #0066cc | #0055b3 | #003d82 | Link blue |
|
|
810
|
+
| #cc0000 | #b30000 | #8b0000 | Error red |
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
**Heading Hierarchy (WCAG 1.3.1)**
|
|
814
|
+
```html
|
|
815
|
+
<!-- Context: Page has 10 H1 elements, skipped H2 levels -->
|
|
816
|
+
|
|
817
|
+
<!-- BEFORE (broken) -->
|
|
818
|
+
<h1>Welcome</h1>
|
|
819
|
+
<h1>Products</h1> <!-- ERROR: Multiple H1s -->
|
|
820
|
+
<h4>Shoes</h4> <!-- ERROR: Skipped H2, H3 -->
|
|
821
|
+
<h1>Contact</h1>
|
|
822
|
+
|
|
823
|
+
<!-- AFTER (correct) -->
|
|
824
|
+
<h1>Site Name - Main Page Title</h1>
|
|
825
|
+
<main>
|
|
826
|
+
<section aria-labelledby="products-heading">
|
|
827
|
+
<h2 id="products-heading">Products</h2>
|
|
828
|
+
<h3>Shoes</h3>
|
|
829
|
+
<h3>Clothing</h3>
|
|
830
|
+
</section>
|
|
831
|
+
<section aria-labelledby="contact-heading">
|
|
832
|
+
<h2 id="contact-heading">Contact</h2>
|
|
833
|
+
</section>
|
|
834
|
+
</main>
|
|
835
|
+
|
|
836
|
+
<!-- HEADING STRUCTURE VISUALIZATION -->
|
|
837
|
+
h1: Site Name - Main Page Title
|
|
838
|
+
├── h2: Products
|
|
839
|
+
│ ├── h3: Shoes
|
|
840
|
+
│ └── h3: Clothing
|
|
841
|
+
└── h2: Contact
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
**Skip Links (WCAG 2.4.1)**
|
|
845
|
+
```html
|
|
846
|
+
<!-- Add as FIRST element inside <body> -->
|
|
847
|
+
<body>
|
|
848
|
+
<a href="#main-content" class="skip-link">Skip to main content</a>
|
|
849
|
+
<a href="#main-nav" class="skip-link">Skip to navigation</a>
|
|
850
|
+
|
|
851
|
+
<header>
|
|
852
|
+
<nav id="main-nav" aria-label="Main navigation">...</nav>
|
|
853
|
+
</header>
|
|
854
|
+
|
|
855
|
+
<main id="main-content" tabindex="-1">
|
|
856
|
+
<!-- Main content -->
|
|
857
|
+
</main>
|
|
858
|
+
</body>
|
|
859
|
+
|
|
860
|
+
<style>
|
|
861
|
+
.skip-link {
|
|
862
|
+
position: absolute;
|
|
863
|
+
top: -100%;
|
|
864
|
+
left: 16px;
|
|
865
|
+
background: #000;
|
|
866
|
+
color: #fff;
|
|
867
|
+
padding: 12px 24px;
|
|
868
|
+
z-index: 10000;
|
|
869
|
+
text-decoration: none;
|
|
870
|
+
font-weight: bold;
|
|
871
|
+
border-radius: 0 0 4px 4px;
|
|
872
|
+
transition: top 0.2s;
|
|
873
|
+
}
|
|
874
|
+
.skip-link:focus {
|
|
875
|
+
top: 0;
|
|
876
|
+
outline: 3px solid #ffcc00;
|
|
877
|
+
outline-offset: 2px;
|
|
878
|
+
}
|
|
879
|
+
</style>
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
**Focus Indicators (WCAG 2.4.7)**
|
|
883
|
+
```css
|
|
884
|
+
/* NEVER do this */
|
|
885
|
+
*:focus { outline: none; } /* WCAG FAIL */
|
|
886
|
+
|
|
887
|
+
/* DO THIS - Custom focus styles */
|
|
888
|
+
:focus-visible {
|
|
889
|
+
outline: 3px solid #005fcc;
|
|
890
|
+
outline-offset: 2px;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/* Remove outline only for mouse users */
|
|
894
|
+
:focus:not(:focus-visible) {
|
|
895
|
+
outline: none;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/* High contrast for interactive elements */
|
|
899
|
+
a:focus-visible,
|
|
900
|
+
button:focus-visible,
|
|
901
|
+
input:focus-visible,
|
|
902
|
+
select:focus-visible,
|
|
903
|
+
textarea:focus-visible,
|
|
904
|
+
[role="button"]:focus-visible {
|
|
905
|
+
outline: 3px solid #005fcc;
|
|
906
|
+
outline-offset: 2px;
|
|
907
|
+
box-shadow: 0 0 0 6px rgba(0, 95, 204, 0.2);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/* Dark backgrounds need light focus */
|
|
911
|
+
.dark-bg :focus-visible {
|
|
912
|
+
outline-color: #ffffff;
|
|
913
|
+
box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.3);
|
|
914
|
+
}
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
**Keyboard Navigation (WCAG 2.1.1, 2.1.2)**
|
|
918
|
+
```html
|
|
919
|
+
<!-- Custom interactive element needs keyboard support -->
|
|
920
|
+
|
|
921
|
+
<!-- BEFORE (inaccessible) -->
|
|
922
|
+
<div class="dropdown" onclick="toggleMenu()">
|
|
923
|
+
Menu
|
|
924
|
+
</div>
|
|
925
|
+
|
|
926
|
+
<!-- AFTER (accessible) -->
|
|
927
|
+
<button type="button"
|
|
928
|
+
class="dropdown-trigger"
|
|
929
|
+
aria-expanded="false"
|
|
930
|
+
aria-controls="dropdown-menu"
|
|
931
|
+
onclick="toggleMenu()"
|
|
932
|
+
onkeydown="handleKeydown(event)">
|
|
933
|
+
Menu
|
|
934
|
+
</button>
|
|
935
|
+
<ul id="dropdown-menu" role="menu" hidden>
|
|
936
|
+
<li role="none"><a role="menuitem" href="/page1">Page 1</a></li>
|
|
937
|
+
<li role="none"><a role="menuitem" href="/page2">Page 2</a></li>
|
|
938
|
+
</ul>
|
|
939
|
+
|
|
940
|
+
<script>
|
|
941
|
+
function handleKeydown(event) {
|
|
942
|
+
switch(event.key) {
|
|
943
|
+
case 'Enter':
|
|
944
|
+
case ' ':
|
|
945
|
+
event.preventDefault();
|
|
946
|
+
toggleMenu();
|
|
947
|
+
break;
|
|
948
|
+
case 'Escape':
|
|
949
|
+
closeMenu();
|
|
950
|
+
break;
|
|
951
|
+
case 'ArrowDown':
|
|
952
|
+
event.preventDefault();
|
|
953
|
+
focusFirstMenuItem();
|
|
954
|
+
break;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
</script>
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
**Modal Focus Trap (WCAG 2.4.3)**
|
|
961
|
+
```javascript
|
|
962
|
+
// Focus trap for modals - REQUIRED for WCAG compliance
|
|
963
|
+
function trapFocus(modal) {
|
|
964
|
+
const focusable = modal.querySelectorAll(
|
|
965
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
966
|
+
);
|
|
967
|
+
const first = focusable[0];
|
|
968
|
+
const last = focusable[focusable.length - 1];
|
|
969
|
+
|
|
970
|
+
// Focus first element when modal opens
|
|
971
|
+
first?.focus();
|
|
972
|
+
|
|
973
|
+
modal.addEventListener('keydown', (e) => {
|
|
974
|
+
if (e.key === 'Tab') {
|
|
975
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
976
|
+
e.preventDefault();
|
|
977
|
+
last.focus();
|
|
978
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
979
|
+
e.preventDefault();
|
|
980
|
+
first.focus();
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (e.key === 'Escape') {
|
|
984
|
+
closeModal();
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// Return focus when modal closes
|
|
990
|
+
function closeModal() {
|
|
991
|
+
modal.hidden = true;
|
|
992
|
+
triggerButton.focus(); // Return focus to trigger
|
|
993
|
+
}
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
**iframe Titles (WCAG 4.1.2)**
|
|
997
|
+
```html
|
|
998
|
+
<!-- All iframes MUST have descriptive titles -->
|
|
999
|
+
<iframe src="map.html" title="Store location map showing 5 nearby stores"></iframe>
|
|
1000
|
+
<iframe src="video.html" title="Product demonstration video with captions"></iframe>
|
|
1001
|
+
<iframe src="chat.html" title="Customer support chat window"></iframe>
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
---
|
|
1005
|
+
|
|
1006
|
+
## STEP 4: USER IMPACT ANALYSIS
|
|
1007
|
+
|
|
1008
|
+
For each violation, calculate user impact:
|
|
1009
|
+
|
|
1010
|
+
### 4.1: Affected User Groups
|
|
1011
|
+
| Violation Type | Affected Groups | % of Users |
|
|
1012
|
+
|----------------|-----------------|------------|
|
|
1013
|
+
| Missing alt text | Blind, low-vision | 7-10% |
|
|
1014
|
+
| Missing form labels | Blind, screen reader users | 5-8% |
|
|
1015
|
+
| Low color contrast | Low-vision, color blind | 8-12% |
|
|
1016
|
+
| No keyboard access | Motor impaired, power users | 10-15% |
|
|
1017
|
+
| Missing captions | Deaf, hard-of-hearing | 5-7% |
|
|
1018
|
+
| Flashing content | Seizure sensitive | 0.5-1% |
|
|
1019
|
+
| Complex language | Cognitive impairment | 10-15% |
|
|
1020
|
+
|
|
1021
|
+
### 4.2: Impact Severity Classification
|
|
1022
|
+
```
|
|
1023
|
+
BLOCKS-USAGE: User cannot complete task at all
|
|
1024
|
+
- Missing form labels on required fields
|
|
1025
|
+
- Keyboard traps
|
|
1026
|
+
- Critical buttons without accessible names
|
|
1027
|
+
|
|
1028
|
+
IMPAIRS-USAGE: User can complete task with difficulty
|
|
1029
|
+
- Low contrast (can read with effort)
|
|
1030
|
+
- Missing skip links (tedious navigation)
|
|
1031
|
+
- Incorrect heading structure (confusing)
|
|
1032
|
+
|
|
1033
|
+
MINOR-INCONVENIENCE: Suboptimal but functional
|
|
1034
|
+
- Empty alt on decorative images
|
|
1035
|
+
- Redundant ARIA
|
|
1036
|
+
- Non-semantic HTML that works
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
---
|
|
1040
|
+
|
|
1041
|
+
## STEP 5: ROI-BASED PRIORITIZATION
|
|
1042
|
+
|
|
1043
|
+
Calculate priority for each remediation:
|
|
1044
|
+
|
|
1045
|
+
### 5.1: Priority Formula
|
|
1046
|
+
```
|
|
1047
|
+
PRIORITY_SCORE = (IMPACT_WEIGHT × USERS_AFFECTED) / EFFORT_HOURS
|
|
1048
|
+
|
|
1049
|
+
Where:
|
|
1050
|
+
- IMPACT_WEIGHT: Critical=10, Serious=7, Moderate=4, Minor=1
|
|
1051
|
+
- USERS_AFFECTED: Estimated % of users impacted
|
|
1052
|
+
- EFFORT_HOURS: Estimated fix time (0.25 to 8 hours)
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
### 5.2: Effort Estimation Guide
|
|
1056
|
+
| Fix Type | Effort | Complexity |
|
|
1057
|
+
|----------|--------|------------|
|
|
1058
|
+
| Add aria-label | 0.25h | Trivial |
|
|
1059
|
+
| Add alt text | 0.25h | Trivial |
|
|
1060
|
+
| Add form label | 0.5h | Simple |
|
|
1061
|
+
| Fix color contrast | 0.5h | Simple |
|
|
1062
|
+
| Add skip links | 1h | Simple |
|
|
1063
|
+
| Fix heading structure | 2h | Medium |
|
|
1064
|
+
| Add keyboard navigation | 4h | High |
|
|
1065
|
+
| Implement focus trap | 4h | High |
|
|
1066
|
+
| Add video captions | 8h | High |
|
|
1067
|
+
|
|
1068
|
+
### 5.3: Priority Output Format
|
|
1069
|
+
```
|
|
1070
|
+
| Rank | Violation | Impact | Users | Effort | ROI Score |
|
|
1071
|
+
|------|-----------|--------|-------|--------|-----------|
|
|
1072
|
+
| 1 | Form labels missing | Critical | 15% | 0.5h | 300 |
|
|
1073
|
+
| 2 | Keyboard trap | Critical | 12% | 4h | 30 |
|
|
1074
|
+
| 3 | Low contrast | Serious | 10% | 0.5h | 140 |
|
|
1075
|
+
| 4 | Missing alt text | Serious | 8% | 0.25h | 224 |
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
---
|
|
1079
|
+
|
|
1080
|
+
## STEP 6: PRODUCTION READINESS ASSESSMENT
|
|
1081
|
+
|
|
1082
|
+
### 6.1: Compliance Scoring
|
|
1083
|
+
```
|
|
1084
|
+
COMPLIANCE_SCORE = (PASSED_CRITERIA / TOTAL_CRITERIA) × 100
|
|
1085
|
+
|
|
1086
|
+
Production Ready if:
|
|
1087
|
+
✓ Score ≥ 85%
|
|
1088
|
+
✓ Zero critical violations
|
|
1089
|
+
✓ Fewer than 3 serious violations
|
|
1090
|
+
✓ All user journeys keyboard accessible
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
### 6.2: POUR Analysis (Perceivable, Operable, Understandable, Robust)
|
|
1094
|
+
```
|
|
1095
|
+
| Principle | Guidelines | Pass | Fail | Score |
|
|
1096
|
+
|-----------|-----------|------|------|-------|
|
|
1097
|
+
| Perceivable | 1.1-1.4 | 12 | 3 | 80% |
|
|
1098
|
+
| Operable | 2.1-2.5 | 18 | 2 | 90% |
|
|
1099
|
+
| Understandable | 3.1-3.3 | 8 | 1 | 89% |
|
|
1100
|
+
| Robust | 4.1 | 4 | 1 | 80% |
|
|
1101
|
+
| **TOTAL** | | **42** | **7** | **86%** |
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
---
|
|
1105
|
+
|
|
1106
|
+
## STEP 7: VIDEO ACCESSIBILITY PIPELINE
|
|
1107
|
+
|
|
1108
|
+
**Execute for EACH video detected on page.**
|
|
1109
|
+
|
|
1110
|
+
### 7.1: Detect and Extract Video URLs (MANDATORY)
|
|
1111
|
+
|
|
1112
|
+
**This step MUST be integrated into STEP 2 multi-tool scan.**
|
|
1113
|
+
|
|
1114
|
+
Add this to the page.evaluate() in the multi-tool scan:
|
|
1115
|
+
```javascript
|
|
1116
|
+
// In pageInfo extraction (STEP 2), add:
|
|
1117
|
+
videos: {
|
|
1118
|
+
elements: [...document.querySelectorAll('video')].map(v => ({
|
|
1119
|
+
src: v.src || v.querySelector('source')?.src,
|
|
1120
|
+
fullUrl: new URL(v.src || v.querySelector('source')?.src || '', window.location.href).href,
|
|
1121
|
+
poster: v.poster,
|
|
1122
|
+
hasCaptions: v.querySelector('track[kind="captions"]') !== null,
|
|
1123
|
+
hasDescriptions: v.querySelector('track[kind="descriptions"]') !== null,
|
|
1124
|
+
duration: v.duration || 'unknown',
|
|
1125
|
+
autoplay: v.autoplay,
|
|
1126
|
+
muted: v.muted
|
|
1127
|
+
})),
|
|
1128
|
+
iframes: [...document.querySelectorAll('iframe')].map(iframe => {
|
|
1129
|
+
const src = iframe.src;
|
|
1130
|
+
const isVideo = /youtube|vimeo|dailymotion|wistia/.test(src);
|
|
1131
|
+
return isVideo ? { src, platform: src.match(/(youtube|vimeo|dailymotion|wistia)/)?.[1] } : null;
|
|
1132
|
+
}).filter(Boolean)
|
|
1133
|
+
}
|
|
1134
|
+
```
|
|
1135
|
+
|
|
1136
|
+
**MANDATORY OUTPUT:** Log all video URLs found:
|
|
1137
|
+
```
|
|
1138
|
+
=== VIDEOS DETECTED ===
|
|
1139
|
+
Video 1: https://example.com/promo.mp4 (no captions, no descriptions)
|
|
1140
|
+
YouTube iframe: https://youtube.com/embed/xxx
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### 7.2: Download and Extract Frames (MANDATORY for each video)
|
|
1144
|
+
|
|
1145
|
+
**For EACH video URL found in 7.1:**
|
|
1146
|
+
|
|
1147
|
+
```bash
|
|
1148
|
+
# Create output directory
|
|
1149
|
+
mkdir -p /tmp/a11y-work/frames
|
|
1150
|
+
|
|
1151
|
+
# Download video (with retry and user-agent)
|
|
1152
|
+
curl -L -A "Mozilla/5.0" --retry 3 -o /tmp/a11y-work/video.mp4 "FULL_VIDEO_URL"
|
|
1153
|
+
|
|
1154
|
+
# Verify download succeeded
|
|
1155
|
+
if [ -f /tmp/a11y-work/video.mp4 ] && [ -s /tmp/a11y-work/video.mp4 ]; then
|
|
1156
|
+
echo "Video downloaded successfully"
|
|
1157
|
+
ffmpeg -i /tmp/a11y-work/video.mp4 -vf "fps=1/3" -frames:v 10 /tmp/a11y-work/frames/frame_%02d.jpg 2>/dev/null
|
|
1158
|
+
echo "Extracted $(ls /tmp/a11y-work/frames/*.jpg 2>/dev/null | wc -l) frames"
|
|
1159
|
+
else
|
|
1160
|
+
echo "VIDEO DOWNLOAD FAILED - Document this in audit-summary.md"
|
|
1161
|
+
fi
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
**IF VIDEO DOWNLOAD FAILS:**
|
|
1165
|
+
1. Document the failure reason in audit-summary.md
|
|
1166
|
+
2. Still create video-captions violation in violations.json
|
|
1167
|
+
3. Add remediation instructions WITHOUT generated captions
|
|
1168
|
+
4. Mark video pipeline as "blocked" not "skipped"
|
|
1169
|
+
|
|
1170
|
+
### 7.3: Analyze Each Frame with Claude Vision (MANDATORY)
|
|
1171
|
+
|
|
1172
|
+
**USE THE READ TOOL ON EACH FRAME IMAGE.**
|
|
1173
|
+
|
|
1174
|
+
Claude Code has native vision capabilities. When you Read an image file, you SEE it.
|
|
1175
|
+
|
|
1176
|
+
```
|
|
1177
|
+
Read /tmp/a11y-work/frames/frame_01.jpg
|
|
1178
|
+
Read /tmp/a11y-work/frames/frame_02.jpg
|
|
1179
|
+
Read /tmp/a11y-work/frames/frame_03.jpg
|
|
1180
|
+
... (continue for all frames)
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
**For EACH frame, describe:**
|
|
1184
|
+
- **SCENE**: Setting, environment, lighting, location
|
|
1185
|
+
- **PEOPLE**: Who appears, what they're doing, expressions, clothing
|
|
1186
|
+
- **PRODUCTS**: Items shown (for e-commerce: product names, colors, styles)
|
|
1187
|
+
- **TEXT**: Any visible text, logos, signs, prices
|
|
1188
|
+
- **ACTION**: Movement, transitions, what's happening
|
|
1189
|
+
|
|
1190
|
+
**Example output after reading frame_01.jpg:**
|
|
1191
|
+
```
|
|
1192
|
+
Frame 1 (0:00-0:03): A woman in white Adidas sneakers running on a forest trail.
|
|
1193
|
+
Morning light filters through trees. She wears black athletic leggings and a
|
|
1194
|
+
gray tank top. The Adidas three-stripe logo is visible on her shoes.
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
**THIS IS THE LLM VALUE.** Generic tools output "[DESCRIBE CONTENT]".
|
|
1198
|
+
You output actual descriptions because you can SEE the image.
|
|
1199
|
+
|
|
1200
|
+
---
|
|
1201
|
+
|
|
1202
|
+
**FALLBACK: If Read tool fails on images**
|
|
1203
|
+
|
|
1204
|
+
Try Anthropic API directly:
|
|
1205
|
+
```javascript
|
|
1206
|
+
const Anthropic = require('@anthropic-ai/sdk');
|
|
1207
|
+
const fs = require('fs');
|
|
1208
|
+
const client = new Anthropic();
|
|
1209
|
+
|
|
1210
|
+
const imageData = fs.readFileSync('/tmp/a11y-work/frames/frame_01.jpg').toString('base64');
|
|
1211
|
+
const response = await client.messages.create({
|
|
1212
|
+
model: 'claude-sonnet-4-20250514',
|
|
1213
|
+
max_tokens: 500,
|
|
1214
|
+
messages: [{
|
|
1215
|
+
role: 'user',
|
|
1216
|
+
content: [
|
|
1217
|
+
{ type: 'image', source: { type: 'base64', media_type: 'image/jpeg', data: imageData } },
|
|
1218
|
+
{ type: 'text', text: 'Describe this video frame for accessibility captions.' }
|
|
1219
|
+
]
|
|
1220
|
+
}]
|
|
1221
|
+
});
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
**LAST RESORT: Context-Based Inference (No Vision)**
|
|
1225
|
+
If vision completely unavailable, infer from:
|
|
1226
|
+
- Video filename: "product-demo.mp4" → product demonstration
|
|
1227
|
+
- Page context: product page → product showcase
|
|
1228
|
+
- Surrounding text: nearby headings and descriptions
|
|
1229
|
+
|
|
1230
|
+
**Document for each frame:**
|
|
1231
|
+
- **SCENE**: Setting, environment, lighting
|
|
1232
|
+
- **PEOPLE**: Who, actions, expressions, clothing
|
|
1233
|
+
- **OBJECTS**: Products, props, equipment
|
|
1234
|
+
- **TEXT**: Visible text, logos, signs
|
|
1235
|
+
- **ACTION**: Movement, transitions
|
|
1236
|
+
- **COLORS**: Dominant colors, accessibility-relevant
|
|
1237
|
+
|
|
1238
|
+
### 7.4: Generate WebVTT Captions
|
|
1239
|
+
```vtt
|
|
1240
|
+
WEBVTT
|
|
1241
|
+
Kind: captions
|
|
1242
|
+
Language: {detected-language}
|
|
1243
|
+
|
|
1244
|
+
00:00:00.000 --> 00:00:03.000
|
|
1245
|
+
[Description from frame_01 analysis]
|
|
1246
|
+
|
|
1247
|
+
00:00:03.000 --> 00:00:06.000
|
|
1248
|
+
[Description from frame_02 analysis]
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
### 7.5: Generate Audio Descriptions
|
|
1252
|
+
```vtt
|
|
1253
|
+
WEBVTT
|
|
1254
|
+
Kind: descriptions
|
|
1255
|
+
Language: en
|
|
1256
|
+
|
|
1257
|
+
00:00:00.000 --> 00:00:03.000
|
|
1258
|
+
SCENE: [Detailed scene for blind users]
|
|
1259
|
+
VISUAL: [What's on screen]
|
|
1260
|
+
TEXT: [Any readable text]
|
|
1261
|
+
ACTION: [What's happening]
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
---
|
|
1265
|
+
|
|
1266
|
+
## STEP 8: GENERATE COMPREHENSIVE REPORTS
|
|
1267
|
+
|
|
1268
|
+
### 8.1: Required Output Files
|
|
1269
|
+
Save ALL files to `docs/accessibility-scans/{page-slug}/`:
|
|
1270
|
+
|
|
1271
|
+
| File | Contents |
|
|
1272
|
+
|------|----------|
|
|
1273
|
+
| `audit-summary.md` | Executive summary, scores, top issues, user impact |
|
|
1274
|
+
| `remediation.md` | **ALL copy-paste code fixes** with context |
|
|
1275
|
+
| `violations.json` | Machine-readable violation data |
|
|
1276
|
+
| `implementation.md` | Video integration guide (if videos) |
|
|
1277
|
+
| `*.vtt` | Caption and audio description files |
|
|
1278
|
+
|
|
1279
|
+
### 8.2: audit-summary.md Template
|
|
1280
|
+
```markdown
|
|
1281
|
+
# Accessibility Audit Report: {Site Name}
|
|
1282
|
+
|
|
1283
|
+
**URL:** {url}
|
|
1284
|
+
**Date:** {date}
|
|
1285
|
+
**Standard:** WCAG 2.2 Level AA
|
|
1286
|
+
|
|
1287
|
+
## Executive Summary
|
|
1288
|
+
|
|
1289
|
+
| Metric | Value |
|
|
1290
|
+
|--------|-------|
|
|
1291
|
+
| **Compliance Score** | {score}% |
|
|
1292
|
+
| **Production Ready** | {Yes/No} |
|
|
1293
|
+
| **Critical Issues** | {count} |
|
|
1294
|
+
| **Total Violations** | {count} |
|
|
1295
|
+
| **Estimated Fix Time** | {hours}h |
|
|
1296
|
+
|
|
1297
|
+
## POUR Analysis
|
|
1298
|
+
{table}
|
|
1299
|
+
|
|
1300
|
+
## Top 10 Issues by Priority
|
|
1301
|
+
{priority table with ROI scores}
|
|
1302
|
+
|
|
1303
|
+
## User Impact Summary
|
|
1304
|
+
{affected user groups and percentages}
|
|
1305
|
+
|
|
1306
|
+
## Recommendations
|
|
1307
|
+
{prioritized action items}
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
### 8.3: remediation.md Template
|
|
1311
|
+
```markdown
|
|
1312
|
+
# Accessibility Remediation Guide: {Site Name}
|
|
1313
|
+
|
|
1314
|
+
## Quick Wins (Copy-Paste Ready)
|
|
1315
|
+
|
|
1316
|
+
### 1. Form Labels ({count} issues)
|
|
1317
|
+
{For EACH unlabeled input: context, before/after code, rationale, confidence}
|
|
1318
|
+
|
|
1319
|
+
### 2. Heading Structure ({count} issues)
|
|
1320
|
+
{Current structure visualization, fixed structure, code changes}
|
|
1321
|
+
|
|
1322
|
+
### 3. Color Contrast ({count} issues)
|
|
1323
|
+
{For EACH: current colors, ratio, suggested colors, CSS fixes}
|
|
1324
|
+
|
|
1325
|
+
### 4. Missing Alt Text ({count} issues)
|
|
1326
|
+
{For EACH image: context-inferred alt text suggestions}
|
|
1327
|
+
|
|
1328
|
+
### 5. Keyboard Navigation ({count} issues)
|
|
1329
|
+
{For EACH: element, issue, fix code, test instructions}
|
|
1330
|
+
|
|
1331
|
+
### 6. Focus Indicators
|
|
1332
|
+
{Global CSS to add}
|
|
1333
|
+
|
|
1334
|
+
### 7. Skip Links
|
|
1335
|
+
{Full HTML + CSS to add}
|
|
1336
|
+
|
|
1337
|
+
### 8. ARIA Fixes ({count} issues)
|
|
1338
|
+
{For EACH: context, specific aria attributes to add}
|
|
1339
|
+
|
|
1340
|
+
### 9. iframe Titles ({count} issues)
|
|
1341
|
+
{For EACH: suggested title based on content}
|
|
1342
|
+
|
|
1343
|
+
### 10. Video Accessibility ({count} videos)
|
|
1344
|
+
{Links to generated VTT files, implementation code}
|
|
1345
|
+
|
|
1346
|
+
## Testing Checklist
|
|
1347
|
+
- [ ] Tab through entire page - all interactive elements reachable
|
|
1348
|
+
- [ ] Screen reader announces all content correctly
|
|
1349
|
+
- [ ] Color contrast passes (use axe DevTools)
|
|
1350
|
+
- [ ] Works without mouse
|
|
1351
|
+
- [ ] Works at 200% zoom
|
|
1352
|
+
- [ ] Video captions synchronized and accurate
|
|
1353
|
+
```
|
|
1354
|
+
|
|
1355
|
+
---
|
|
1356
|
+
|
|
1357
|
+
## STEP 9: LEARNING PROTOCOL (When MCP Available)
|
|
1358
|
+
|
|
1359
|
+
Integrate with the learning system to improve over time.
|
|
1360
|
+
|
|
1361
|
+
### 9.1: Query Previous Patterns BEFORE Audit
|
|
1362
|
+
|
|
1363
|
+
Check if similar sites were audited before:
|
|
1364
|
+
```javascript
|
|
1365
|
+
// Load MCP tools
|
|
1366
|
+
ToolSearch("select:mcp__claude-flow_alpha__memory_retrieve")
|
|
1367
|
+
ToolSearch("select:mcp__claude-flow_alpha__hooks_intelligence_pattern_search")
|
|
1368
|
+
|
|
1369
|
+
// Retrieve domain-specific patterns
|
|
1370
|
+
mcp__claude-flow_alpha__memory_retrieve({
|
|
1371
|
+
key: `accessibility/patterns/${domain}`,
|
|
1372
|
+
namespace: "learning"
|
|
1373
|
+
})
|
|
1374
|
+
|
|
1375
|
+
// Search for similar violation patterns
|
|
1376
|
+
mcp__claude-flow_alpha__hooks_intelligence_pattern_search({
|
|
1377
|
+
query: "accessibility remediation",
|
|
1378
|
+
type: "accessibility-fix",
|
|
1379
|
+
limit: 10
|
|
1380
|
+
})
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
### 9.2: Store Successful Patterns AFTER Audit
|
|
1384
|
+
|
|
1385
|
+
Store patterns that worked for future reuse:
|
|
1386
|
+
```javascript
|
|
1387
|
+
ToolSearch("select:mcp__claude-flow_alpha__memory_store")
|
|
1388
|
+
ToolSearch("select:mcp__claude-flow_alpha__hooks_intelligence_pattern_store")
|
|
1389
|
+
|
|
1390
|
+
// Store audit outcome
|
|
1391
|
+
mcp__claude-flow_alpha__memory_store({
|
|
1392
|
+
key: `accessibility-audit/${domain}-${Date.now()}`,
|
|
1393
|
+
namespace: "learning",
|
|
1394
|
+
value: {
|
|
1395
|
+
url: auditedUrl,
|
|
1396
|
+
timestamp: new Date().toISOString(),
|
|
1397
|
+
violationsFound: violations.length,
|
|
1398
|
+
criticalCount: violations.filter(v => v.impact === 'critical').length,
|
|
1399
|
+
toolsUsed: ['axe-core', 'pa11y', 'lighthouse'],
|
|
1400
|
+
patterns: {
|
|
1401
|
+
commonViolations: extractTopViolationTypes(violations),
|
|
1402
|
+
effectiveFixes: extractFixesThatWorked(remediations)
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
})
|
|
1406
|
+
|
|
1407
|
+
// Store reusable remediation patterns
|
|
1408
|
+
mcp__claude-flow_alpha__hooks_intelligence_pattern_store({
|
|
1409
|
+
pattern: "form-label-contextual-fix",
|
|
1410
|
+
confidence: 0.92,
|
|
1411
|
+
type: "accessibility-remediation",
|
|
1412
|
+
metadata: {
|
|
1413
|
+
wcagCriteria: "1.3.1, 3.3.2, 4.1.2",
|
|
1414
|
+
violationType: "missing-form-label",
|
|
1415
|
+
codeTemplate: "<label for=\"{id}\">{inferredLabel}</label>",
|
|
1416
|
+
contextSignals: ["placeholder", "nearby-text", "field-name"]
|
|
1417
|
+
}
|
|
1418
|
+
})
|
|
1419
|
+
```
|
|
1420
|
+
|
|
1421
|
+
### 9.3: Calculate Audit Quality Score
|
|
1422
|
+
|
|
1423
|
+
Self-assess audit completeness (for learning feedback):
|
|
1424
|
+
|
|
1425
|
+
| Criteria | Points | Your Score |
|
|
1426
|
+
|----------|--------|------------|
|
|
1427
|
+
| Multi-tool testing used (3 tools) | 20 | |
|
|
1428
|
+
| All WCAG 2.2 AA criteria checked | 15 | |
|
|
1429
|
+
| Context-aware fixes generated | 20 | |
|
|
1430
|
+
| Confidence scores included | 10 | |
|
|
1431
|
+
| ROI prioritization calculated | 10 | |
|
|
1432
|
+
| Video pipeline completed (if applicable) | 15 | |
|
|
1433
|
+
| EU compliance mapping included | 10 | |
|
|
1434
|
+
| **Total** | **100** | |
|
|
1435
|
+
|
|
1436
|
+
**Quality Levels:**
|
|
1437
|
+
- 90-100: Excellent (1.0 reward)
|
|
1438
|
+
- 70-89: Good (0.8 reward)
|
|
1439
|
+
- 50-69: Acceptable (0.5 reward)
|
|
1440
|
+
- <50: Incomplete (0.0 reward - redo required)
|
|
1441
|
+
|
|
1442
|
+
---
|
|
1443
|
+
|
|
1444
|
+
## STEP 10: SCREEN READER TESTING GUIDE
|
|
1445
|
+
|
|
1446
|
+
Manual testing instructions (cannot be fully automated):
|
|
1447
|
+
|
|
1448
|
+
### 10.1: NVDA (Windows - Free)
|
|
1449
|
+
```
|
|
1450
|
+
1. Download: https://www.nvaccess.org/download/
|
|
1451
|
+
2. Install and start NVDA (Ctrl+Alt+N)
|
|
1452
|
+
3. Navigate to audited page
|
|
1453
|
+
|
|
1454
|
+
Key Commands:
|
|
1455
|
+
- H: Jump through headings
|
|
1456
|
+
- F: Jump through form fields
|
|
1457
|
+
- B: Jump through buttons
|
|
1458
|
+
- T: Jump through tables
|
|
1459
|
+
- K: Jump through links
|
|
1460
|
+
- D: Jump through landmarks
|
|
1461
|
+
- Tab: Move through focusable elements
|
|
1462
|
+
|
|
1463
|
+
Verify:
|
|
1464
|
+
- [ ] All headings announced with correct level
|
|
1465
|
+
- [ ] Form fields announce labels
|
|
1466
|
+
- [ ] Buttons announce purpose
|
|
1467
|
+
- [ ] Images announce alt text or "decorative"
|
|
1468
|
+
- [ ] Dynamic content changes announced (aria-live)
|
|
1469
|
+
```
|
|
1470
|
+
|
|
1471
|
+
### 10.2: VoiceOver (macOS - Built-in)
|
|
1472
|
+
```
|
|
1473
|
+
1. Enable: System Preferences → Accessibility → VoiceOver
|
|
1474
|
+
2. Toggle: Cmd+F5
|
|
1475
|
+
3. Navigate to audited page
|
|
1476
|
+
|
|
1477
|
+
Key Commands:
|
|
1478
|
+
- VO+U: Open rotor (headings, links, forms, landmarks)
|
|
1479
|
+
- VO+Space: Activate element
|
|
1480
|
+
- VO+Right/Left: Move through content
|
|
1481
|
+
- VO+Cmd+H: Jump to next heading
|
|
1482
|
+
|
|
1483
|
+
Verify:
|
|
1484
|
+
- [ ] Rotor shows all headings hierarchically
|
|
1485
|
+
- [ ] Forms are navigable and labels announced
|
|
1486
|
+
- [ ] Focus order matches visual order
|
|
1487
|
+
- [ ] All content is reachable
|
|
1488
|
+
```
|
|
1489
|
+
|
|
1490
|
+
### 10.3: JAWS (Windows - Commercial)
|
|
1491
|
+
```
|
|
1492
|
+
1. Trial: https://www.freedomscientific.com/products/software/jaws/
|
|
1493
|
+
2. Start JAWS and navigate to page
|
|
1494
|
+
|
|
1495
|
+
Key Commands:
|
|
1496
|
+
- H: Next heading
|
|
1497
|
+
- F: Next form field
|
|
1498
|
+
- B: Next button
|
|
1499
|
+
- T: Next table
|
|
1500
|
+
- Ins+F6: Heading list
|
|
1501
|
+
- Ins+F7: Link list
|
|
1502
|
+
|
|
1503
|
+
Verify:
|
|
1504
|
+
- [ ] Virtual cursor mode works correctly
|
|
1505
|
+
- [ ] Forms mode activates in forms
|
|
1506
|
+
- [ ] All ARIA roles announced properly
|
|
1507
|
+
```
|
|
1508
|
+
|
|
1509
|
+
### 10.4: Screen Reader Testing Checklist
|
|
1510
|
+
|
|
1511
|
+
| Test | NVDA | VoiceOver | JAWS |
|
|
1512
|
+
|------|------|-----------|------|
|
|
1513
|
+
| Headings hierarchy correct | [ ] | [ ] | [ ] |
|
|
1514
|
+
| Form labels announced | [ ] | [ ] | [ ] |
|
|
1515
|
+
| Button purposes clear | [ ] | [ ] | [ ] |
|
|
1516
|
+
| Image alt text correct | [ ] | [ ] | [ ] |
|
|
1517
|
+
| Links announce destination | [ ] | [ ] | [ ] |
|
|
1518
|
+
| Landmarks navigable | [ ] | [ ] | [ ] |
|
|
1519
|
+
| Focus order logical | [ ] | [ ] | [ ] |
|
|
1520
|
+
| Dynamic updates announced | [ ] | [ ] | [ ] |
|
|
1521
|
+
| No keyboard traps | [ ] | [ ] | [ ] |
|
|
1522
|
+
| Skip links work | [ ] | [ ] | [ ] |
|
|
1523
|
+
|
|
1524
|
+
---
|
|
1525
|
+
|
|
1526
|
+
## VALIDATION CHECKLIST
|
|
1527
|
+
|
|
1528
|
+
Before completing, verify ALL items:
|
|
1529
|
+
|
|
1530
|
+
### Content Fetching (v7.0 Resilient)
|
|
1531
|
+
- [ ] Browser launched (Vibium/agent-browser/Playwright)
|
|
1532
|
+
- [ ] Page loaded and analyzed
|
|
1533
|
+
- [ ] Multi-tool scan ran with **parallel execution**
|
|
1534
|
+
- [ ] At least **1 of 3 tools succeeded** (graceful degradation)
|
|
1535
|
+
- [ ] If tools failed, documented **which tools and why**
|
|
1536
|
+
- [ ] Results saved to `/tmp/a11y-work/scan-results.json`
|
|
1537
|
+
|
|
1538
|
+
### Violation Analysis
|
|
1539
|
+
- [ ] All violations extracted with WCAG criteria
|
|
1540
|
+
- [ ] Context analyzed for each violation
|
|
1541
|
+
- [ ] User impact calculated
|
|
1542
|
+
|
|
1543
|
+
### Remediation Generation
|
|
1544
|
+
- [ ] Form label fixes with context and rationale
|
|
1545
|
+
- [ ] Heading hierarchy fix with visualization
|
|
1546
|
+
- [ ] Color contrast fixes with hex codes
|
|
1547
|
+
- [ ] Alt text suggestions with confidence scores
|
|
1548
|
+
- [ ] Skip link code (full HTML + CSS)
|
|
1549
|
+
- [ ] Focus indicator CSS
|
|
1550
|
+
- [ ] ARIA fixes with specific attributes
|
|
1551
|
+
- [ ] Keyboard navigation fixes
|
|
1552
|
+
- [ ] iframe titles
|
|
1553
|
+
|
|
1554
|
+
### Video Accessibility (MANDATORY if pageInfo.media.videos > 0)
|
|
1555
|
+
- [ ] Video URLs extracted (full URLs, not relative)
|
|
1556
|
+
- [ ] Download attempted for EACH video
|
|
1557
|
+
- [ ] IF download succeeded: Frames extracted with ffmpeg
|
|
1558
|
+
- [ ] IF download succeeded: Each frame analyzed with Read tool
|
|
1559
|
+
- [ ] IF download succeeded: captions.vtt generated from ACTUAL frame descriptions
|
|
1560
|
+
- [ ] IF download succeeded: audiodesc.vtt generated
|
|
1561
|
+
- [ ] IF download FAILED: Failure documented in audit-summary.md with reason
|
|
1562
|
+
- [ ] IF download FAILED: Manual captioning instructions in remediation.md
|
|
1563
|
+
|
|
1564
|
+
**BLOCKING:** Cannot generate final reports until video pipeline attempted.
|
|
1565
|
+
|
|
1566
|
+
### Output Files
|
|
1567
|
+
- [ ] audit-summary.md with scores, priorities, and user impact
|
|
1568
|
+
- [ ] remediation.md with ALL copy-paste code fixes
|
|
1569
|
+
- [ ] violations.json with violation data
|
|
1570
|
+
- [ ] VTT files (if videos)
|
|
1571
|
+
- [ ] implementation.md (if videos)
|
|
1572
|
+
|
|
1573
|
+
### Quality Checks
|
|
1574
|
+
- [ ] Compliance score calculated
|
|
1575
|
+
- [ ] Production readiness assessed
|
|
1576
|
+
- [ ] ROI prioritization completed
|
|
1577
|
+
- [ ] POUR analysis included
|
|
1578
|
+
|
|
1579
|
+
**IF ANY CHECKBOX IS NO = TASK INCOMPLETE**
|
|
1580
|
+
</default_to_action>
|
|
1581
|
+
|
|
1582
|
+
---
|
|
1583
|
+
|
|
1584
|
+
## Quick Reference Card
|
|
1585
|
+
|
|
1586
|
+
### Usage
|
|
1587
|
+
```
|
|
1588
|
+
/a11y-ally https://example.com
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
### v7.0 Resilience Features
|
|
1592
|
+
| Feature | Description |
|
|
1593
|
+
|---------|-------------|
|
|
1594
|
+
| **Parallel Execution** | All 3 tools run simultaneously via Promise.allSettled |
|
|
1595
|
+
| **Per-Tool Timeouts** | axe: 60s, pa11y: 60s, Lighthouse: 90s |
|
|
1596
|
+
| **Retry with Backoff** | 2 retries per tool with exponential backoff |
|
|
1597
|
+
| **Graceful Degradation** | Continue if 1+ tools succeed |
|
|
1598
|
+
| **Progressive Output** | Results stream as tools complete |
|
|
1599
|
+
| **Bot Protection** | Stealth mode, random delays, cookie dismissal |
|
|
1600
|
+
|
|
1601
|
+
### Expected Output Structure
|
|
1602
|
+
```
|
|
1603
|
+
docs/accessibility-scans/{page-slug}/
|
|
1604
|
+
├── audit-summary.md # Executive summary with scores
|
|
1605
|
+
├── remediation.md # ALL copy-paste code fixes
|
|
1606
|
+
├── violations.json # Machine-readable data
|
|
1607
|
+
├── implementation.md # Video integration (if videos)
|
|
1608
|
+
├── video-*-captions.vtt # Captions (if videos)
|
|
1609
|
+
└── video-*-audiodesc.vtt # Audio descriptions (if videos)
|
|
1610
|
+
```
|
|
1611
|
+
|
|
1612
|
+
### Compliance Thresholds
|
|
1613
|
+
| Level | Min Score | Critical | Serious |
|
|
1614
|
+
|-------|-----------|----------|---------|
|
|
1615
|
+
| A | 70% | 0 | ≤5 |
|
|
1616
|
+
| AA | 85% | 0 | ≤3 |
|
|
1617
|
+
| AAA | 95% | 0 | 0 |
|
|
1618
|
+
|
|
1619
|
+
### Tool Coverage by Success
|
|
1620
|
+
| Tools Succeeded | Detection Rate | Status |
|
|
1621
|
+
|-----------------|---------------|--------|
|
|
1622
|
+
| 3/3 | ~95% | ✅ Optimal |
|
|
1623
|
+
| 2/3 | ~85% | ⚠️ Good |
|
|
1624
|
+
| 1/3 | ~70% | ⚠️ Acceptable |
|
|
1625
|
+
| 0/3 | — | ❌ Retry needed |
|
|
1626
|
+
|
|
1627
|
+
### ROI Formula
|
|
1628
|
+
```
|
|
1629
|
+
ROI = (Impact × Users%) / Effort_Hours
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
---
|
|
1633
|
+
|
|
1634
|
+
## EU Compliance Mapping
|
|
1635
|
+
|
|
1636
|
+
| WCAG | EN 301 549 | EU Accessibility Act |
|
|
1637
|
+
|------|------------|---------------------|
|
|
1638
|
+
| 1.1.1 | 9.1.1.1 | EAA-I.1 Perceivable |
|
|
1639
|
+
| 1.4.3 | 9.1.4.3 | EAA-I.1 Perceivable |
|
|
1640
|
+
| 2.1.1 | 9.2.1.1 | EAA-I.2 Operable |
|
|
1641
|
+
| 2.4.7 | 9.2.4.7 | EAA-I.2 Operable |
|
|
1642
|
+
| 3.3.2 | 9.3.3.2 | EAA-I.3 Understandable |
|
|
1643
|
+
| 4.1.2 | 9.4.1.2 | EAA-I.4 Robust |
|
|
1644
|
+
|
|
1645
|
+
---
|
|
1646
|
+
|
|
1647
|
+
## Critical Rules
|
|
1648
|
+
|
|
1649
|
+
### Execution Rules (v7.0)
|
|
1650
|
+
1. **ALWAYS** run multi-tool scan with **parallel execution** (Promise.allSettled)
|
|
1651
|
+
2. **ALWAYS** continue if at least **1 of 3 tools** succeeds (graceful degradation)
|
|
1652
|
+
3. **ALWAYS** document which tools failed and why in audit-summary.md
|
|
1653
|
+
4. **ALWAYS** use per-tool timeouts (60s/60s/90s) not global timeout
|
|
1654
|
+
5. **ALWAYS** retry failed tools with exponential backoff before giving up
|
|
1655
|
+
|
|
1656
|
+
### Quality Rules
|
|
1657
|
+
6. **ALWAYS** analyze context before generating fixes
|
|
1658
|
+
7. **ALWAYS** include confidence scores with remediation
|
|
1659
|
+
8. **ALWAYS** calculate user impact and ROI
|
|
1660
|
+
9. **ALWAYS** generate copy-paste ready code
|
|
1661
|
+
10. **NEVER** generate placeholder/template fixes
|
|
1662
|
+
11. **NEVER** skip video pipeline if videos detected
|
|
1663
|
+
12. **NEVER** complete without remediation.md
|
|
1664
|
+
13. **NEVER** fail audit just because 1-2 tools failed (use graceful degradation)
|