@mcptoolshop/accessibility-suite 0.1.0 → 0.2.0

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.
Files changed (75) hide show
  1. package/.a11y_artifacts_test/evidence.json +52 -0
  2. package/.a11y_artifacts_test/gate-result.json +41 -0
  3. package/.a11y_artifacts_test/report.txt +19 -0
  4. package/.github/actions/a11y-ci/action.yml +106 -0
  5. package/.github/workflows/a11y-gate.yml +112 -0
  6. package/.github/workflows/ci.yml +68 -3
  7. package/.github/workflows/test-a11y-action.yml +93 -0
  8. package/.github/workflows/update-baseline.yml +49 -0
  9. package/.github/workflows/verify-docs.yml +26 -0
  10. package/CHANGELOG.md +33 -0
  11. package/GETTING_STARTED.md +87 -0
  12. package/HANDBOOK.md +747 -0
  13. package/README.md +202 -23
  14. package/assets/a11y-logo.png +0 -0
  15. package/docs/handbooks/A11Y-ASSIST.md +31 -0
  16. package/docs/handbooks/A11Y-CI.md +71 -0
  17. package/docs/handbooks/A11Y-DEMO-SITE.md +29 -0
  18. package/docs/handbooks/A11Y-EVIDENCE-ENGINE.md +31 -0
  19. package/docs/handbooks/A11Y-LINT.md +62 -0
  20. package/docs/handbooks/A11Y-MCP-TOOLS.md +34 -0
  21. package/docs/handbooks/ACCESSIBILITY-SUITE.md +51 -0
  22. package/docs/handbooks/ALLY-DEMO-PYTHON.md +23 -0
  23. package/docs/handbooks/COMMON-CONCEPTS.md +24 -0
  24. package/docs/handbooks/CURSORASSIST.md +18 -0
  25. package/docs/handbooks/README.md +20 -0
  26. package/docs/prov-spec/SETUP.md +1 -1
  27. package/docs/rules.md +132 -0
  28. package/docs/unified-artifacts.md +52 -0
  29. package/logo.png +0 -0
  30. package/package.json +1 -1
  31. package/pipelines/templates/a11y-ci.yml +135 -0
  32. package/pipelines/test-a11y-ci-template.yml +36 -0
  33. package/scripts/verify_handbooks.py +97 -0
  34. package/src/a11y-assist/README.md +5 -0
  35. package/src/a11y-ci/.a11y_artifacts_test/current.scorecard.json +11 -0
  36. package/src/a11y-ci/.a11y_artifacts_test/evidence.json +52 -0
  37. package/src/a11y-ci/.a11y_artifacts_test/gate-result.json +41 -0
  38. package/src/a11y-ci/.a11y_artifacts_test/report.txt +19 -0
  39. package/src/a11y-ci/README.md +83 -23
  40. package/src/a11y-ci/a11y_ci/allowlist.py +52 -9
  41. package/src/a11y-ci/a11y_ci/cli.py +143 -46
  42. package/src/a11y-ci/a11y_ci/error_ids.py +17 -0
  43. package/src/a11y-ci/a11y_ci/gate.py +83 -48
  44. package/src/a11y-ci/a11y_ci/help.py +119 -0
  45. package/src/a11y-ci/a11y_ci/mcp_payload.py +124 -0
  46. package/src/a11y-ci/a11y_ci/pr_comment.py +127 -0
  47. package/src/a11y-ci/a11y_ci/report.py +137 -0
  48. package/src/a11y-ci/a11y_ci/schema/scorecard.schema.json +89 -0
  49. package/src/a11y-ci/a11y_ci/schemas/allowlist.schema.json +11 -2
  50. package/src/a11y-ci/a11y_ci/scorecard.py +86 -30
  51. package/src/a11y-ci/a11y_ci/severity.py +29 -0
  52. package/src/a11y-ci/npm/README.md +47 -0
  53. package/src/a11y-ci/npm/package.json +1 -1
  54. package/src/a11y-ci/tests/fixtures/allowlist_expired.json +2 -1
  55. package/src/a11y-ci/tests/fixtures/allowlist_ok.json +2 -1
  56. package/src/a11y-ci/tests/fixtures/baseline_ok.json +17 -4
  57. package/src/a11y-ci/tests/fixtures/current_fail.json +10 -3
  58. package/src/a11y-ci/tests/fixtures/current_failures_many.json +11 -0
  59. package/src/a11y-ci/tests/fixtures/current_ok.json +10 -3
  60. package/src/a11y-ci/tests/fixtures/current_regresses.json +15 -4
  61. package/src/a11y-ci/tests/test_allowlist_v2.py +97 -0
  62. package/src/a11y-ci/tests/test_gate.py +3 -3
  63. package/src/a11y-ci/tests/test_mcp_cli.py +80 -0
  64. package/src/a11y-ci/tests/test_mcp_payload.py +76 -0
  65. package/src/a11y-ci/tests/test_polish.py +83 -0
  66. package/src/a11y-ci/tests/test_pr_comment.py +103 -0
  67. package/src/a11y-ci/tests/test_rule_help.py +70 -0
  68. package/src/a11y-ci/tests/test_schema_validation.py +36 -0
  69. package/src/a11y-ci/tests/test_scorecard_canonical.py +88 -0
  70. package/src/a11y-ci/tests/test_smoke_cli.py +41 -0
  71. package/src/a11y-evidence-engine/README.md +5 -0
  72. package/src/a11y-lint/README.md +5 -0
  73. package/src/a11y-lint/a11y_lint/cli.py +29 -0
  74. package/src/a11y-mcp-tools/README.md +5 -0
  75. package/tools/ado/a11y-ci.ps1 +195 -0
@@ -0,0 +1,52 @@
1
+ {
2
+ "tool": "a11y-ci",
3
+ "tool_version": "0.1.0",
4
+ "run_id": "56a4a7ea-f8e8-40a9-a27b-aec92f9c96aa",
5
+ "timestamp": "2026-02-15T02:15:35.804358+00:00",
6
+ "repo": null,
7
+ "commit_sha": null,
8
+ "workflow": null,
9
+ "gate": {
10
+ "decision": "fail",
11
+ "exit_code": 3,
12
+ "fail_on": "serious",
13
+ "counts": {
14
+ "info": 0,
15
+ "minor": 0,
16
+ "moderate": 0,
17
+ "serious": 3,
18
+ "critical": 0
19
+ },
20
+ "deltas": {}
21
+ },
22
+ "blocking": [
23
+ {
24
+ "id": "TEST.001",
25
+ "fingerprint": "7c61e0b75cae921316221a4e5c756285e3e8837086df60a627332fbdf53c7196",
26
+ "severity": "serious",
27
+ "message": "msg",
28
+ "location": null
29
+ },
30
+ {
31
+ "id": "TEST.002",
32
+ "fingerprint": "ed70b4e75a112074812a72be997ffe074ff9d0eec48fe4b0a7d00fc15d546782",
33
+ "severity": "serious",
34
+ "message": "msg",
35
+ "location": null
36
+ },
37
+ {
38
+ "id": "TEST.003",
39
+ "fingerprint": "1fb34777b302157e998e8db92c9be20c9e1316649c2edfb825151dcaca45df56",
40
+ "severity": "serious",
41
+ "message": "msg",
42
+ "location": null
43
+ }
44
+ ],
45
+ "artifacts": [
46
+ {
47
+ "kind": "scorecard",
48
+ "path": "tests/fixtures/current_failures_many.json",
49
+ "sha256": "93d6c211476cb614b30e30256c9644d7b7694d0a67ca72bfc0a872cb4fb57196"
50
+ }
51
+ ]
52
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "gate": "FAIL",
3
+ "timestamp": "ISO8601-TODO",
4
+ "counts": {
5
+ "info": 0,
6
+ "minor": 0,
7
+ "moderate": 0,
8
+ "serious": 3,
9
+ "critical": 0
10
+ },
11
+ "baseline_counts": null,
12
+ "reasons": [
13
+ "Current run has 3 finding(s) at or above 'serious'."
14
+ ],
15
+ "blocking": {
16
+ "current_ids": [
17
+ "TEST.001",
18
+ "TEST.002",
19
+ "TEST.003"
20
+ ],
21
+ "details": [
22
+ {
23
+ "id": "TEST.001",
24
+ "help_url": null,
25
+ "help_hint": null
26
+ },
27
+ {
28
+ "id": "TEST.002",
29
+ "help_url": null,
30
+ "help_hint": null
31
+ },
32
+ {
33
+ "id": "TEST.003",
34
+ "help_url": null,
35
+ "help_hint": null
36
+ }
37
+ ],
38
+ "new_ids": [],
39
+ "new_fingerprints": []
40
+ }
41
+ }
@@ -0,0 +1,19 @@
1
+ [ERROR] Accessibility gate failed (ID: A11Y.CI.GATE.FAIL)
2
+
3
+ What:
4
+ Accessibility policy violations were detected.
5
+
6
+ Summary:
7
+ Serious: 3
8
+
9
+ Why:
10
+ Current run has 3 finding(s) at or above 'serious'.
11
+
12
+ Fix:
13
+ Address the listed findings or update the baseline.
14
+ Run local check: a11y-ci gate --current <path>
15
+
16
+ Blocking IDs (Top 10):
17
+ - TEST.001
18
+ - TEST.002
19
+ - TEST.003
@@ -0,0 +1,106 @@
1
+ name: 'Accessibility Gate (a11y-ci)'
2
+ description: 'Runs a11y-ci policy gate with unified artifact handling.'
3
+ inputs:
4
+ artifact-dir:
5
+ description: 'Directory to store artifacts'
6
+ required: false
7
+ default: '.a11y_artifacts'
8
+ current:
9
+ description: 'Path to current scorecard JSON (optional if in artifact-dir)'
10
+ required: false
11
+ baseline:
12
+ description: 'Path to baseline scorecard JSON (optional if in artifact-dir)'
13
+ required: false
14
+ allowlist:
15
+ description: 'Path to allowlist JSON (optional if in artifact-dir)'
16
+ required: false
17
+ fail-on:
18
+ description: 'Minimum severity to fail on (info, minor, moderate, serious, critical)'
19
+ required: false
20
+ default: 'serious'
21
+ top:
22
+ description: 'Limit N blocking findings in output'
23
+ required: false
24
+ default: '10'
25
+ platform:
26
+ description: 'Markdown flavor for PR comments (github or ado)'
27
+ required: false
28
+ default: 'github'
29
+ post-comment:
30
+ description: 'Whether to prepare a PR comment file'
31
+ required: false
32
+ default: 'true'
33
+
34
+ outputs:
35
+ exit_code:
36
+ description: 'Exit code of the gate'
37
+ value: ${{ steps.gate.outputs.exit_code }}
38
+ evidence_path:
39
+ description: 'Path to the generated evidence JSON'
40
+ value: ${{ steps.gate.outputs.evidence_path }}
41
+ comment_path:
42
+ description: 'Path to the generated PR comment markdown'
43
+ value: ${{ steps.gate.outputs.comment_path }}
44
+ gate_result_path:
45
+ description: 'Path to the generated gate result JSON'
46
+ value: ${{ steps.gate.outputs.gate_result_path }}
47
+
48
+ runs:
49
+ using: "composite"
50
+ steps:
51
+ - name: Run Accessibility Gate
52
+ id: gate
53
+ shell: bash
54
+ run: |
55
+ # 1. Setup Artifacts
56
+ ARTIFACT_DIR="${{ inputs.artifact-dir }}"
57
+ mkdir -p "$ARTIFACT_DIR"
58
+ echo "Using artifact directory: $ARTIFACT_DIR"
59
+
60
+ # 2. Construct Arguments
61
+ ARGS="gate --artifact-dir $ARTIFACT_DIR"
62
+
63
+ if [ -n "${{ inputs.current }}" ]; then
64
+ ARGS="$ARGS --current ${{ inputs.current }}"
65
+ fi
66
+
67
+ if [ -n "${{ inputs.baseline }}" ]; then
68
+ ARGS="$ARGS --baseline ${{ inputs.baseline }}"
69
+ fi
70
+
71
+ if [ -n "${{ inputs.allowlist }}" ]; then
72
+ ARGS="$ARGS --allowlist ${{ inputs.allowlist }}"
73
+ fi
74
+
75
+ ARGS="$ARGS --fail-on ${{ inputs.fail-on }}"
76
+ ARGS="$ARGS --top ${{ inputs.top }}"
77
+
78
+ # 3. Run Gate
79
+ echo "Running: a11y-ci $ARGS"
80
+
81
+ # Run and capture exit code, but don't fail immediately so we can process artifacts
82
+ set +e
83
+ a11y-ci $ARGS
84
+ EXIT_CODE=$?
85
+ set -e
86
+
87
+ echo "Gate Exit Code: $EXIT_CODE"
88
+ echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
89
+
90
+ # 4. Generate Comment (if requested and evidence exists)
91
+ EVIDENCE_JSON="$ARTIFACT_DIR/evidence.json"
92
+ COMMENT_MD="$ARTIFACT_DIR/comment.md"
93
+ GATE_RESULT="$ARTIFACT_DIR/gate-result.json"
94
+
95
+ if [ "${{ inputs.post-comment }}" = "true" ] && [ -f "$EVIDENCE_JSON" ]; then
96
+ echo "Generating PR Comment..."
97
+ a11y-ci comment --mcp "$EVIDENCE_JSON" --platform "${{ inputs.platform }}" --top "${{ inputs.top }}" > "$COMMENT_MD"
98
+ echo "comment_path=$COMMENT_MD" >> $GITHUB_OUTPUT
99
+ fi
100
+
101
+ # 5. Set Outputs
102
+ echo "evidence_path=$EVIDENCE_JSON" >> $GITHUB_OUTPUT
103
+ echo "gate_result_path=$GATE_RESULT" >> $GITHUB_OUTPUT
104
+
105
+ # 6. Exit with code
106
+ exit $EXIT_CODE
@@ -0,0 +1,112 @@
1
+ name: Accessibility Gate
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - '**/*.md'
8
+ - '**/*.html'
9
+ - 'src/**'
10
+ pull_request:
11
+ branches: [main]
12
+ paths:
13
+ - '**/*.md'
14
+ - '**/*.html'
15
+ - 'src/**'
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+ checks: write
21
+ pull-requests: write # For posting comments (later step)
22
+
23
+ jobs:
24
+ accessibility-gate:
25
+ name: Accessibility Compliance
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - name: Checkout Code
29
+ uses: actions/checkout@v4
30
+
31
+ - name: Setup Python
32
+ uses: actions/setup-python@v5
33
+ with:
34
+ python-version: '3.11'
35
+
36
+ # In a real repo, you'd pip install a11y-lint a11y-ci
37
+ # Here we install from local source for dogfooding
38
+ - name: Install Tools (Local)
39
+ run: |
40
+ pip install ./src/a11y-lint
41
+ pip install ./src/a11y-ci
42
+
43
+ - name: Generate Scorecard (Scan)
44
+ run: |
45
+ mkdir -p .a11y_artifacts
46
+ # Scanning docs for demonstration
47
+ # Uses --artifact-dir to automatically write current.scorecard.json
48
+ a11y-lint scan docs --artifact-dir .a11y_artifacts
49
+ echo "Generated scorecard in .a11y_artifacts/"
50
+
51
+ # The reusable Action
52
+ - name: Run Accessibility Gate
53
+ id: gate
54
+ uses: ./.github/actions/a11y-ci
55
+ with:
56
+ artifact-dir: .a11y_artifacts
57
+ baseline: docs/baselines/a11y.scorecard.json
58
+ fail-on: serious
59
+ platform: github
60
+
61
+ - name: Post PR Comment
62
+ if: github.event_name == 'pull_request' && (success() || failure())
63
+ uses: actions/github-script@v7
64
+ with:
65
+ script: |
66
+ const fs = require('fs');
67
+ // Read the generated comment file
68
+ const commentPath = '${{ steps.gate.outputs.comment_path }}';
69
+ if (!commentPath || !fs.existsSync(commentPath)) {
70
+ console.log('No comment file to post.');
71
+ return;
72
+ }
73
+ const body = fs.readFileSync(commentPath, 'utf8');
74
+ const marker = '<!-- a11y-ci-sticky-comment -->';
75
+ const fullBody = `${marker}\n${body}`;
76
+
77
+ const { owner, repo } = context.repo;
78
+ const issue_number = context.issue.number;
79
+
80
+ // Find existing comment
81
+ const comments = await github.rest.issues.listComments({
82
+ owner,
83
+ repo,
84
+ issue_number,
85
+ });
86
+
87
+ const existing = comments.data.find(c => c.body.includes(marker));
88
+
89
+ if (existing) {
90
+ await github.rest.issues.updateComment({
91
+ owner,
92
+ repo,
93
+ comment_id: existing.id,
94
+ body: fullBody,
95
+ });
96
+ console.log(`Updated comment ${existing.id}`);
97
+ } else {
98
+ await github.rest.issues.createComment({
99
+ owner,
100
+ repo,
101
+ issue_number,
102
+ body: fullBody,
103
+ });
104
+ console.log('Created new comment');
105
+ }
106
+
107
+ - name: Upload Artifacts
108
+ if: always()
109
+ uses: actions/upload-artifact@v4
110
+ with:
111
+ name: accessibility-artifacts
112
+ path: .a11y_artifacts/**
@@ -6,6 +6,10 @@ on:
6
6
  pull_request:
7
7
  branches: [main]
8
8
 
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
9
13
  jobs:
10
14
  # Python projects: a11y-assist, a11y-ci, a11y-lint
11
15
  python:
@@ -25,6 +29,7 @@ jobs:
25
29
  uses: actions/setup-python@v5
26
30
  with:
27
31
  python-version: '3.11'
32
+ cache: 'pip'
28
33
 
29
34
  - name: Install dependencies
30
35
  working-directory: src/${{ matrix.project }}
@@ -34,7 +39,18 @@ jobs:
34
39
 
35
40
  - name: Run tests
36
41
  working-directory: src/${{ matrix.project }}
37
- run: pytest -v || echo "No tests or tests failed"
42
+ # Check if tests exist (exit code 5 = no tests). If they exist, run them and fail on error.
43
+ run: |
44
+ pytest --collect-only > /dev/null 2>&1
45
+ EXIT_CODE=$?
46
+ if [ $EXIT_CODE -eq 5 ]; then
47
+ echo "::warning::No tests found for ${{ matrix.project }}."
48
+ exit 0
49
+ elif [ $EXIT_CODE -ne 0 ]; then
50
+ echo "::error::Error collecting tests."
51
+ exit 1
52
+ fi
53
+ pytest -v
38
54
 
39
55
  # Node.js projects: a11y-evidence-engine, a11y-mcp-tools
40
56
  nodejs:
@@ -53,11 +69,60 @@ jobs:
53
69
  uses: actions/setup-node@v4
54
70
  with:
55
71
  node-version: '20'
72
+ cache: 'npm'
56
73
 
57
74
  - name: Install dependencies
58
75
  working-directory: src/${{ matrix.project }}
59
76
  run: npm ci
60
77
 
61
- - name: Run tests
78
+ - name: Run tests (CI Must Fail)
62
79
  working-directory: src/${{ matrix.project }}
63
- run: npm test || echo "No tests or tests failed"
80
+ # If npm test script exits non-zero, fail the build.
81
+ # This prevents accidental regressions from being swallowed.
82
+ run: npm test
83
+
84
+ # Integration fixture verification for a11y-ci
85
+ gate-verification:
86
+ runs-on: ubuntu-latest
87
+ steps:
88
+ - uses: actions/checkout@v4
89
+ - uses: actions/setup-python@v5
90
+ with:
91
+ python-version: '3.11'
92
+ cache: 'pip'
93
+
94
+ - name: Install a11y-ci
95
+ working-directory: src/a11y-ci
96
+ run: pip install .
97
+
98
+ - name: Gate Pass Check
99
+ working-directory: src/a11y-ci
100
+ run: a11y-ci gate --current tests/fixtures/current_ok.json
101
+
102
+ - name: Gate Fail Check (JSON Report)
103
+ id: fail_check
104
+ working-directory: src/a11y-ci
105
+ # We expect failure (exit code 3), so we use || true to prevent job failure,
106
+ # but capture output. In a real pipeline, we'd want to fail if it DOESN'T fail.
107
+ run: |
108
+ set +e
109
+ a11y-ci gate --current tests/fixtures/current_fail.json --format json > report.json
110
+ EXIT_CODE=$?
111
+ set -e
112
+
113
+ echo "Exit Code: $EXIT_CODE"
114
+ if [ $EXIT_CODE -ne 3 ]; then
115
+ echo "::error::Expected exit code 3 for partial failure, got $EXIT_CODE"
116
+ exit 1
117
+ fi
118
+
119
+ echo "::group::JSON Report"
120
+ cat report.json
121
+ echo "::endgroup::"
122
+
123
+ - name: Upload Gate Artifacts
124
+ if: always()
125
+ uses: actions/upload-artifact@v4
126
+ with:
127
+ name: a11y-gate-report
128
+ path: src/a11y-ci/report.json
@@ -0,0 +1,93 @@
1
+ name: Test Accessibility Action (Integration)
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - '.github/actions/a11y-ci/**'
8
+ - '.github/workflows/test-a11y-action.yml'
9
+ pull_request:
10
+ branches: [main]
11
+ paths:
12
+ - '.github/actions/a11y-ci/**'
13
+ - '.github/workflows/test-a11y-action.yml'
14
+
15
+ jobs:
16
+ test-pass:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: '3.11'
23
+
24
+ - name: Install a11y-ci
25
+ run: pip install ./src/a11y-ci
26
+
27
+ - name: Create Passing Scorecard
28
+ run: |
29
+ echo '{"meta": {"tool": "test", "version": "1"}, "findings": []}' > pass.json
30
+
31
+ - name: Run Action (Pass)
32
+ id: gate
33
+ uses: ./.github/actions/a11y-ci
34
+ with:
35
+ current: pass.json
36
+ fail-on: serious
37
+ # Use console output for testing
38
+ post-comment: true
39
+
40
+ - name: Assert Outcomes
41
+ if: steps.gate.outputs.exit_code != '0'
42
+ run: |
43
+ echo "Expected exit code 0, got ${{ steps.gate.outputs.exit_code }}"
44
+ exit 1
45
+
46
+ - name: Assert Artifacts
47
+ run: |
48
+ if [ ! -f "${{ steps.gate.outputs.report_json_path }}" ]; then exit 1; fi
49
+ if [ ! -f "${{ steps.gate.outputs.mcp_payload_path }}" ]; then exit 1; fi
50
+ if [ ! -f "${{ steps.gate.outputs.comment_md_path }}" ]; then exit 1; fi
51
+
52
+ # Check comment content
53
+ if ! grep -q "Accessibility Gate: PASS" "${{ steps.gate.outputs.comment_md_path }}"; then
54
+ echo "Comment does not indicate PASS"
55
+ cat "${{ steps.gate.outputs.comment_md_path }}"
56
+ exit 1
57
+ fi
58
+
59
+ test-fail:
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ - uses: actions/setup-python@v5
64
+ with:
65
+ python-version: '3.11'
66
+
67
+ - name: Install a11y-ci
68
+ run: pip install ./src/a11y-ci
69
+
70
+ - name: Create Failing Scorecard
71
+ run: |
72
+ echo '{"meta": {"tool": "test", "version": "1"}, "findings": [{"id": "FAIL", "severity": "serious", "message": "fail"}]}' > fail.json
73
+
74
+ - name: Run Action (Fail)
75
+ id: gate
76
+ continue-on-error: true
77
+ uses: ./.github/actions/a11y-ci
78
+ with:
79
+ current: fail.json
80
+ fail-on: serious
81
+
82
+ - name: Assert Outcomes
83
+ if: steps.gate.outputs.exit_code != '3'
84
+ run: |
85
+ echo "Expected exit code 3, got ${{ steps.gate.outputs.exit_code }}"
86
+ exit 1
87
+
88
+ - name: Assert Comment Content
89
+ run: |
90
+ if ! grep -q "Accessibility Gate: FAIL" "${{ steps.gate.outputs.comment_md_path }}"; then
91
+ echo "Comment does not indicate FAIL"
92
+ exit 1
93
+ fi
@@ -0,0 +1,49 @@
1
+ name: Update Baseline
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ reason:
7
+ description: 'Reason for updating baseline (e.g., new feature, temporary failure)'
8
+ required: true
9
+
10
+ permissions:
11
+ contents: write
12
+
13
+ jobs:
14
+ update-baseline:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout Code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+
25
+ # Install Tools
26
+ - name: Install Tools (Local)
27
+ run: |
28
+ pip install ./src/a11y-lint
29
+ pip install ./src/a11y-ci
30
+
31
+ # Scan
32
+ - name: Generate Scorecard (Scan)
33
+ run: |
34
+ a11y-lint scan docs --format json > docs/baselines/a11y.scorecard.json
35
+
36
+ # Detect changes and commit
37
+ - name: Commit Baseline
38
+ run: |
39
+ git config --global user.name 'a11y-ci-bot'
40
+ git config --global user.email 'a11y-ci-bot@users.noreply.github.com'
41
+
42
+ if git diff --quiet docs/baselines/a11y.scorecard.json; then
43
+ echo "No changes in baseline."
44
+ else
45
+ git add docs/baselines/a11y.scorecard.json
46
+ git commit -m "chore(baseline): update a11y baseline" -m "${{ github.event.inputs.reason }}"
47
+ git push
48
+ echo "Baseline updated."
49
+ fi
@@ -0,0 +1,26 @@
1
+ name: Verify Documentation
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - 'docs/handbooks/**'
7
+ - 'scripts/verify_handbooks.py'
8
+ pull_request:
9
+ paths:
10
+ - 'docs/handbooks/**'
11
+ - 'scripts/verify_handbooks.py'
12
+ workflow_dispatch:
13
+
14
+ jobs:
15
+ verify-handbooks:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+
25
+ - name: Verify Handbooks
26
+ run: python scripts/verify_handbooks.py
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-02-17
9
+
10
+ ### Added
11
+
12
+ - Product-focused README.md replacing the migration notice with suite value proposition, architecture overview, project table, quick start guides, MCP client configuration, and documentation links.
13
+ - HANDBOOK.md with comprehensive documentation covering the accessibility testing problem space, architecture deep dives for all six sub-projects, evidence-based testing with prov-spec provenance, CI integration patterns (GitHub Actions and Azure DevOps), MCP integration guide, development setup for the multi-language monorepo, and FAQ.
14
+ - CHANGELOG.md in Keep a Changelog format.
15
+ - MIT license badge in README.md.
16
+
17
+ ## [0.1.0] - 2026-02-12
18
+
19
+ ### Added
20
+
21
+ - Initial monorepo structure consolidating six accessibility tools.
22
+ - a11y-lint: accessibility linter for CLI output with WCAG and policy rules.
23
+ - a11y-ci: CI gate for accessibility scorecards with regression detection and allowlists.
24
+ - a11y-assist: low-vision-first CLI assistant with five accessibility profiles (lowvision, cognitive-load, screen-reader, dyslexia, plain-language).
25
+ - a11y-evidence-engine: headless HTML scanner with prov-spec provenance records.
26
+ - a11y-mcp-tools: MCP server exposing evidence capture and diagnosis tools.
27
+ - a11y-demo-site: demo site with intentional violations for end-to-end testing.
28
+ - Unified artifact strategy with `.a11y_artifacts/` directory convention.
29
+ - GETTING_STARTED.md with three-command local setup and CI templates.
30
+ - prov-spec documentation in `docs/prov-spec/`.
31
+
32
+ [0.2.0]: https://github.com/mcp-tool-shop-org/accessibility-suite/compare/v0.1.0...v0.2.0
33
+ [0.1.0]: https://github.com/mcp-tool-shop-org/accessibility-suite/releases/tag/v0.1.0