mobile-ai-agents 1.0.23
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/AGENTS.md +228 -0
- package/CLAUDE.md +236 -0
- package/LICENSE +21 -0
- package/README.md +652 -0
- package/agents/android/android-crash-analyzer/README.md +134 -0
- package/agents/android/android-crash-analyzer/agent.md +206 -0
- package/agents/android/android-crash-analyzer/example-input.md +138 -0
- package/agents/android/android-crash-analyzer/example-output.md +225 -0
- package/agents/android/anr-investigation/README.md +78 -0
- package/agents/android/anr-investigation/agent.md +117 -0
- package/agents/android/anr-investigation/example-input.md +62 -0
- package/agents/android/anr-investigation/example-output.md +103 -0
- package/agents/android/axiom/agent.md +197 -0
- package/agents/android/code-reviewer/README.md +108 -0
- package/agents/android/code-reviewer/agent.md +210 -0
- package/agents/android/code-reviewer/example-input.md +116 -0
- package/agents/android/code-reviewer/example-output.md +115 -0
- package/agents/android/compose-navigation/README.md +76 -0
- package/agents/android/compose-navigation/agent.md +121 -0
- package/agents/android/compose-navigation/example-input.md +49 -0
- package/agents/android/compose-navigation/example-output.md +325 -0
- package/agents/android/compose-screen-builder/README.md +95 -0
- package/agents/android/compose-screen-builder/agent.md +170 -0
- package/agents/android/compose-screen-builder/example-input.md +40 -0
- package/agents/android/compose-screen-builder/example-output.md +568 -0
- package/agents/android/compose-ui-reviewer/README.md +73 -0
- package/agents/android/compose-ui-reviewer/agent.md +253 -0
- package/agents/android/compose-ui-reviewer/example-input.md +84 -0
- package/agents/android/compose-ui-reviewer/example-output.md +102 -0
- package/agents/android/crash-analyzer/README.md +53 -0
- package/agents/android/crash-analyzer/agent.md +295 -0
- package/agents/android/memory-leak-analyzer/README.md +79 -0
- package/agents/android/memory-leak-analyzer/agent.md +116 -0
- package/agents/android/memory-leak-analyzer/example-input.md +78 -0
- package/agents/android/memory-leak-analyzer/example-output.md +128 -0
- package/agents/cross-platform/accessibility-auditor/README.md +47 -0
- package/agents/cross-platform/accessibility-auditor/agent.md +268 -0
- package/agents/cross-platform/accessibility-auditor/example-input.md +84 -0
- package/agents/cross-platform/accessibility-auditor/example-output.md +132 -0
- package/agents/cross-platform/appforge/agent.md +303 -0
- package/agents/cross-platform/ci-cd-generator/README.md +65 -0
- package/agents/cross-platform/ci-cd-generator/agent.md +422 -0
- package/agents/cross-platform/ci-cd-generator/example-input.md +69 -0
- package/agents/cross-platform/ci-cd-generator/example-output.md +261 -0
- package/agents/cross-platform/crasher/agent.md +221 -0
- package/agents/cross-platform/figma/agent.md +247 -0
- package/agents/cross-platform/launchpad/agent.md +330 -0
- package/agents/cross-platform/mobile-harness/agent.md +422 -0
- package/agents/cross-platform/mobile-memory/agent.md +429 -0
- package/agents/cross-platform/perf/agent.md +261 -0
- package/agents/cross-platform/pipeline/agent.md +288 -0
- package/agents/cross-platform/release-notes-generator/README.md +63 -0
- package/agents/cross-platform/release-notes-generator/agent.md +218 -0
- package/agents/cross-platform/release-notes-generator/example-input.md +71 -0
- package/agents/cross-platform/release-notes-generator/example-output.md +96 -0
- package/agents/cross-platform/scribe/agent.md +180 -0
- package/agents/cross-platform/security-scanner/README.md +61 -0
- package/agents/cross-platform/security-scanner/agent.md +287 -0
- package/agents/cross-platform/security-scanner/example-input.md +77 -0
- package/agents/cross-platform/security-scanner/example-output.md +141 -0
- package/agents/cross-platform/sentinel/agent.md +217 -0
- package/agents/cross-platform/store-listing-writer/README.md +58 -0
- package/agents/cross-platform/store-listing-writer/agent.md +380 -0
- package/agents/cross-platform/store-listing-writer/example-input.md +67 -0
- package/agents/cross-platform/store-listing-writer/example-output.md +131 -0
- package/agents/flutter/bloc-feature-builder/README.md +101 -0
- package/agents/flutter/bloc-feature-builder/agent.md +225 -0
- package/agents/flutter/bloc-feature-builder/example-input.md +47 -0
- package/agents/flutter/bloc-feature-builder/example-output.md +838 -0
- package/agents/flutter/dart/agent.md +223 -0
- package/agents/flutter/widget-generator/README.md +66 -0
- package/agents/flutter/widget-generator/agent.md +264 -0
- package/agents/flutter/widget-generator/example-input.md +71 -0
- package/agents/flutter/widget-generator/example-output.md +163 -0
- package/agents/gaming/forge/agent.md +197 -0
- package/agents/gaming/unreal/agent.md +200 -0
- package/agents/ios/crash-analyzer/README.md +69 -0
- package/agents/ios/crash-analyzer/agent.md +300 -0
- package/agents/ios/crash-analyzer/example-input.md +83 -0
- package/agents/ios/crash-analyzer/example-output.md +126 -0
- package/agents/ios/swift/agent.md +206 -0
- package/agents/ios/swift-reviewer/README.md +68 -0
- package/agents/ios/swift-reviewer/agent.md +231 -0
- package/agents/ios/swift-reviewer/example-input.md +100 -0
- package/agents/ios/swift-reviewer/example-output.md +127 -0
- package/agents/react-native/bridge/agent.md +212 -0
- package/agents/react-native/performance-optimizer/README.md +81 -0
- package/agents/react-native/performance-optimizer/agent.md +284 -0
- package/agents/react-native/performance-optimizer/example-input.md +104 -0
- package/agents/react-native/performance-optimizer/example-output.md +132 -0
- package/agents/unity/shader-generator/README.md +77 -0
- package/agents/unity/shader-generator/agent.md +270 -0
- package/agents/unity/shader-generator/example-input.md +70 -0
- package/agents/unity/shader-generator/example-output.md +160 -0
- package/agents/unreal/blueprint-advisor/README.md +71 -0
- package/agents/unreal/blueprint-advisor/agent.md +311 -0
- package/agents/unreal/blueprint-advisor/example-input.md +73 -0
- package/agents/unreal/blueprint-advisor/example-output.md +217 -0
- package/cli/index.js +1091 -0
- package/docs/agent-guide.md +138 -0
- package/docs/chatgpt-integration.md +219 -0
- package/docs/core-loops.md +143 -0
- package/docs/cursor-integration.md +143 -0
- package/docs/getting-started.md +132 -0
- package/docs/index.html +711 -0
- package/docs/installation.md +271 -0
- package/docs/mobile-harness.md +160 -0
- package/docs/mobile-mcp.md +172 -0
- package/docs/mobile-memory.md +349 -0
- package/docs/release-process.md +85 -0
- package/docs/releases/release-v1.0.0.md +165 -0
- package/docs/roadmap/github-issues.md +239 -0
- package/docs/skill-categories.md +125 -0
- package/docs/vscode-copilot-integration.md +104 -0
- package/docs/wiki.md +615 -0
- package/install.sh +507 -0
- package/mobile-karpathy.md +79 -0
- package/package.json +57 -0
- package/skills/android/README.md +31 -0
- package/skills/android/android-tdd.md +89 -0
- package/skills/android/anr-investigation.md +251 -0
- package/skills/android/code-review.md +98 -0
- package/skills/android/compose-migration.md +48 -0
- package/skills/android/compose-review.md +78 -0
- package/skills/android/kotlin-modernize.md +51 -0
- package/skills/android/memory-leak-investigation.md +256 -0
- package/skills/android/proguard-rules.md +48 -0
- package/skills/cross-platform/accessibility-audit.md +63 -0
- package/skills/cross-platform/api-versioning.md +59 -0
- package/skills/cross-platform/clean-code-audit.md +239 -0
- package/skills/cross-platform/crash-triage.md +53 -0
- package/skills/cross-platform/deeplink-debug.md +57 -0
- package/skills/cross-platform/feature-slice.md +48 -0
- package/skills/cross-platform/grill-mobile.md +64 -0
- package/skills/cross-platform/mobile-mcp-qa.md +193 -0
- package/skills/cross-platform/mobile-memory-graph.md +179 -0
- package/skills/cross-platform/mobile-memory-save.md +210 -0
- package/skills/cross-platform/mobile-memory-search.md +154 -0
- package/skills/cross-platform/perf-audit.md +61 -0
- package/skills/cross-platform/prd-verification.md +324 -0
- package/skills/cross-platform/release-prep.md +64 -0
- package/skills/cross-platform/security-audit.md +281 -0
- package/skills/cross-platform/store-listing.md +75 -0
- package/skills/flutter/README.md +32 -0
- package/skills/flutter/dart-modernize.md +47 -0
- package/skills/flutter/flutter-review.md +59 -0
- package/skills/flutter/flutter-tdd.md +73 -0
- package/skills/flutter/widget-extract.md +41 -0
- package/skills/flutter/widget-gen.md +131 -0
- package/skills/gaming/blueprint-to-cpp.md +51 -0
- package/skills/gaming/game-perf.md +54 -0
- package/skills/gaming/shader-gen.md +44 -0
- package/skills/gaming/unity-tdd.md +85 -0
- package/skills/ios/README.md +45 -0
- package/skills/ios/data-persistence.md +151 -0
- package/skills/ios/ios-tdd.md +90 -0
- package/skills/ios/networking.md +139 -0
- package/skills/ios/performance.md +122 -0
- package/skills/ios/swift-concurrency.md +57 -0
- package/skills/ios/swift-review.md +124 -0
- package/skills/ios/swiftui-review.md +49 -0
- package/skills/ios/swiftui-state.md +122 -0
- package/skills/ios/unit-testing.md +144 -0
- package/skills/ios/xcode-warnings.md +37 -0
- package/skills/react-native/README.md +42 -0
- package/skills/react-native/bridge-audit.md +104 -0
- package/skills/react-native/expo-optimize.md +55 -0
- package/skills/react-native/new-arch-migrate.md +53 -0
- package/skills/react-native/performance.md +124 -0
- package/skills/react-native/rn-review.md +53 -0
- package/skills/react-native/rn-tdd.md +76 -0
- package/skills/shared/README.md +46 -0
- package/skills/shared/accessibility-audit.md +132 -0
- package/skills/shared/crash-analysis.md +110 -0
- package/skills/shared/security-scan.md +149 -0
- package/skills/unity/README.md +31 -0
- package/skills/unity/shader-review.md +110 -0
- package/templates/agent-template.md +88 -0
- package/templates/prompt-template.md +50 -0
- package/templates/skill-template.md +64 -0
- package/templates/workflow-template.md +48 -0
- package/workflows/app-launch.md +66 -0
- package/workflows/appforge-workflow.md +232 -0
- package/workflows/ci-setup.md +77 -0
- package/workflows/crash-to-fix.md +71 -0
- package/workflows/feature-ship.md +61 -0
- package/workflows/game-level.md +72 -0
- package/workflows/mobile-harness.md +319 -0
- package/workflows/mobile-mcp-qa.md +228 -0
- package/workflows/mobile-memory-workflow.md +243 -0
- package/workflows/new-project-setup.md +93 -0
- package/workflows/new-screen.md +68 -0
- package/workflows/perf-sprint.md +78 -0
- package/workflows/release-cycle.md +71 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Accessibility Auditor Agent
|
|
2
|
+
|
|
3
|
+
> Paste a UI component. Get a WCAG 2.2-aligned accessibility audit with CRITICAL / HIGH / MEDIUM / LOW findings and platform-specific fixes for Compose, SwiftUI, Flutter, or React Native.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What This Agent Does
|
|
8
|
+
|
|
9
|
+
Reviews mobile UI code for accessibility compliance across all four major mobile UI frameworks:
|
|
10
|
+
|
|
11
|
+
- **Content labels** — missing `contentDescription`, `accessibilityLabel`, or `Semantics(label:)` on interactive/meaningful elements
|
|
12
|
+
- **Touch targets** — elements below 48dp (Android) or 44pt (iOS/Flutter/RN) minimum
|
|
13
|
+
- **Roles and traits** — buttons not announced as buttons, toggles without state (`isSelected`, `checked`)
|
|
14
|
+
- **Focus order** — visual vs. hierarchy mismatch, focus not trapped in modals
|
|
15
|
+
- **Dynamic announcements** — state changes (loading complete, error shown) not announced to screen readers
|
|
16
|
+
- **Grouping** — related elements read as separate items when they should be combined
|
|
17
|
+
|
|
18
|
+
Every finding includes: element name, what a screen reader currently announces, what it should announce, the WCAG 2.2 criterion, and the corrected code.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Files
|
|
23
|
+
|
|
24
|
+
| File | Purpose |
|
|
25
|
+
|---|---|
|
|
26
|
+
| [`agent.md`](agent.md) | Input format, output format, full system prompt |
|
|
27
|
+
| [`example-input.md`](example-input.md) | Compose TaskItem with missing labels and small tap target |
|
|
28
|
+
| [`example-output.md`](example-output.md) | Full WCAG-annotated accessibility audit |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
PLATFORM: <Android-Compose | Android-XML | iOS-SwiftUI | iOS-UIKit | Flutter | React-Native>
|
|
36
|
+
FILE_PATH: <relative path>
|
|
37
|
+
CODE:
|
|
38
|
+
[paste the UI component]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Related Agents
|
|
44
|
+
|
|
45
|
+
- [`agents/cross-platform/security-scanner`](../security-scanner/) — pair with this for a complete pre-release audit
|
|
46
|
+
- `skills/shared/accessibility-audit.md` — quick inline accessibility checklist
|
|
47
|
+
- `prompts/ios/swiftui-accessibility.md` — SwiftUI-only accessibility audit prompt
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Agent 12 — Accessibility Auditor
|
|
2
|
+
|
|
3
|
+
**Platform:** Cross-Platform (Android / iOS / Flutter / React Native)
|
|
4
|
+
**Category:** Code Quality / Accessibility
|
|
5
|
+
**Complexity:** Medium
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Reviews mobile UI code for accessibility compliance across Android (Compose/XML), iOS (SwiftUI/UIKit), Flutter, and React Native. Returns a severity-ranked findings report covering missing labels, touch target sizes, dynamic content announcements, focus order, and screen reader behavior. Each finding includes the exact fix for the target platform.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Input Format
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
PLATFORM: <Android-Compose | Android-XML | iOS-SwiftUI | iOS-UIKit | Flutter | React-Native>
|
|
19
|
+
FILE_PATH: <relative path>
|
|
20
|
+
CODE:
|
|
21
|
+
<paste the UI component or screen code>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Fields:**
|
|
25
|
+
|
|
26
|
+
| Field | Required | Description |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `PLATFORM` | Yes | Specific platform and UI framework |
|
|
29
|
+
| `FILE_PATH` | Yes | Used to infer component role |
|
|
30
|
+
| `CODE` | Yes | UI source code to audit |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Output Format
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
ACCESSIBILITY AUDIT
|
|
38
|
+
===================
|
|
39
|
+
File: <file path>
|
|
40
|
+
Platform: <platform>
|
|
41
|
+
Issues Found: <count>
|
|
42
|
+
Critical: <count> High: <count> Medium: <count> Low: <count>
|
|
43
|
+
|
|
44
|
+
FINDINGS
|
|
45
|
+
--------
|
|
46
|
+
[CRITICAL] <Issue title>
|
|
47
|
+
Element : <UI element or widget>
|
|
48
|
+
Problem : <What is missing and who is blocked>
|
|
49
|
+
WCAG : <WCAG 2.2 criterion, e.g. 1.1.1 Non-text Content>
|
|
50
|
+
Fix :
|
|
51
|
+
<corrected code snippet in target platform>
|
|
52
|
+
|
|
53
|
+
[HIGH] <Issue title>
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
[MEDIUM] / [LOW]
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
SCREEN READER ASSESSMENT
|
|
60
|
+
-------------------------
|
|
61
|
+
TalkBack / VoiceOver compatibility: <PASS / PARTIAL / FAIL>
|
|
62
|
+
→ <Summary of what a screen reader user would experience>
|
|
63
|
+
|
|
64
|
+
TOUCH TARGET AUDIT
|
|
65
|
+
------------------
|
|
66
|
+
All targets ≥48dp (Android) / 44pt (iOS): <Yes / No>
|
|
67
|
+
→ <List of elements that fail the minimum>
|
|
68
|
+
|
|
69
|
+
DYNAMIC CONTENT
|
|
70
|
+
---------------
|
|
71
|
+
State changes announced: <Yes / No / N/A>
|
|
72
|
+
→ <Explanation>
|
|
73
|
+
|
|
74
|
+
OVERALL VERDICT: <PASS / NEEDS WORK / INACCESSIBLE>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## System Prompt
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
You are a senior mobile accessibility engineer with expertise in WCAG 2.2, Android TalkBack,
|
|
83
|
+
iOS VoiceOver, Flutter Semantics, and React Native Accessibility API. Your job is to review
|
|
84
|
+
mobile UI code for accessibility issues and produce a structured, actionable audit report.
|
|
85
|
+
|
|
86
|
+
For each finding:
|
|
87
|
+
- Assign severity: CRITICAL (blocks screen reader users entirely), HIGH (degrades usability
|
|
88
|
+
significantly), MEDIUM (impacts some users), LOW (minor improvement).
|
|
89
|
+
- Reference the relevant WCAG 2.2 criterion (e.g., 1.1.1 Non-text Content, 2.5.5 Target Size).
|
|
90
|
+
- Provide the exact fix in the platform's native accessibility API — not pseudocode.
|
|
91
|
+
|
|
92
|
+
Checks to perform:
|
|
93
|
+
|
|
94
|
+
CONTENT DESCRIPTIONS / LABELS (WCAG 1.1.1)
|
|
95
|
+
- Every interactive element that doesn't contain descriptive text children needs a label.
|
|
96
|
+
- Labels describe the ACTION, not the icon: "Delete task" not "Trash icon".
|
|
97
|
+
- Decorative images/icons must be explicitly hidden from the accessibility tree.
|
|
98
|
+
- Android Compose: Modifier.semantics { contentDescription = "..." } or Icon(contentDescription = "...")
|
|
99
|
+
- Android XML: android:contentDescription or android:labelFor
|
|
100
|
+
- iOS SwiftUI: .accessibilityLabel("..."), .accessibilityHidden(true) for decorative
|
|
101
|
+
- iOS UIKit: view.accessibilityLabel, view.isAccessibilityElement = false for decorative
|
|
102
|
+
- Flutter: Semantics(label: "..."), ExcludeSemantics for decorative
|
|
103
|
+
- React Native: accessibilityLabel="...", accessibilityElementsHidden={true} for decorative
|
|
104
|
+
|
|
105
|
+
TOUCH TARGET SIZE (WCAG 2.5.5)
|
|
106
|
+
- Minimum 48×48 dp (Android) / 44×44 pt (iOS / Flutter / RN) for all interactive elements.
|
|
107
|
+
- Android Compose: Modifier.minimumInteractiveComponentSize() or Modifier.size(48.dp).wrapContentSize()
|
|
108
|
+
- iOS SwiftUI: .frame(minWidth: 44, minHeight: 44) or .contentShape(Rectangle())
|
|
109
|
+
- Flutter: SizedBox(width: 48, height: 48, child: ...) or GestureDetector with padding
|
|
110
|
+
- React Native: minHeight: 44, minWidth: 44 in StyleSheet, or hitSlop
|
|
111
|
+
|
|
112
|
+
ROLES AND TRAITS (WCAG 4.1.2)
|
|
113
|
+
- Buttons must be announced as buttons, not generic "view" or "image".
|
|
114
|
+
- Android Compose: Modifier.semantics { role = Role.Button }
|
|
115
|
+
- iOS SwiftUI: .accessibilityAddTraits(.isButton)
|
|
116
|
+
- Flutter: Semantics(button: true)
|
|
117
|
+
- React Native: accessibilityRole="button"
|
|
118
|
+
- Toggles, checkboxes, sliders: assign the correct role AND state.
|
|
119
|
+
|
|
120
|
+
FOCUS ORDER AND GROUPING (WCAG 1.3.2, 2.4.3)
|
|
121
|
+
- Logical reading order must match visual order. Flag absolute-positioned elements
|
|
122
|
+
where the hierarchy order differs from the visual order.
|
|
123
|
+
- Group related elements: Android Compose Modifier.semantics(mergeDescendants = true),
|
|
124
|
+
iOS UIAccessibilityContainer, Flutter MergeSemantics, React Native accessible={true}.
|
|
125
|
+
- Modal dialogs: focus must be trapped inside the modal when it opens.
|
|
126
|
+
React Native: accessibilityViewIsModal={true}
|
|
127
|
+
iOS: UIAccessibility.post(notification: .screenChanged, argument: firstModalElement)
|
|
128
|
+
|
|
129
|
+
DYNAMIC CONTENT ANNOUNCEMENTS (WCAG 4.1.3)
|
|
130
|
+
- When content changes dynamically (success, error, counter update, loading complete),
|
|
131
|
+
announce it to screen readers:
|
|
132
|
+
Android: View.announceForAccessibility("...") or Modifier.semantics { liveRegion = LiveRegionMode.Polite }
|
|
133
|
+
iOS: UIAccessibility.post(notification: .announcement, argument: "...")
|
|
134
|
+
Flutter: SemanticsService.announce("...", TextDirection.ltr)
|
|
135
|
+
React Native: AccessibilityInfo.announceForAccessibility("...")
|
|
136
|
+
- Flag any dynamic state change (snackbar, badge, loading indicator hiding) with no announcement.
|
|
137
|
+
|
|
138
|
+
Output MUST follow the exact format specified.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Example
|
|
144
|
+
|
|
145
|
+
### Input
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
PLATFORM: Android-Compose
|
|
149
|
+
FILE_PATH: ui/components/TaskItem.kt
|
|
150
|
+
CODE:
|
|
151
|
+
@Composable
|
|
152
|
+
fun TaskItem(
|
|
153
|
+
task: Task,
|
|
154
|
+
onDelete: (String) -> Unit,
|
|
155
|
+
onToggle: (String) -> Unit
|
|
156
|
+
) {
|
|
157
|
+
Row(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
|
|
158
|
+
Checkbox(
|
|
159
|
+
checked = task.isDone,
|
|
160
|
+
onCheckedChange = { onToggle(task.id) }
|
|
161
|
+
)
|
|
162
|
+
Text(
|
|
163
|
+
text = task.title,
|
|
164
|
+
modifier = Modifier.weight(1f)
|
|
165
|
+
)
|
|
166
|
+
IconButton(
|
|
167
|
+
onClick = { onDelete(task.id) },
|
|
168
|
+
modifier = Modifier.size(24.dp)
|
|
169
|
+
) {
|
|
170
|
+
Icon(Icons.Default.Delete, contentDescription = null)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Output
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
ACCESSIBILITY AUDIT
|
|
180
|
+
===================
|
|
181
|
+
File: ui/components/TaskItem.kt
|
|
182
|
+
Platform: Android-Compose
|
|
183
|
+
Issues Found: 3
|
|
184
|
+
Critical: 1 High: 1 Medium: 1 Low: 0
|
|
185
|
+
|
|
186
|
+
FINDINGS
|
|
187
|
+
--------
|
|
188
|
+
[CRITICAL] Icon button has no accessibility label
|
|
189
|
+
Element : IconButton with Icons.Default.Delete
|
|
190
|
+
Problem : contentDescription = null means TalkBack announces this as "button" with
|
|
191
|
+
no indication of its function. Screen reader users cannot know it deletes
|
|
192
|
+
the task without exploring by trial and error.
|
|
193
|
+
WCAG : 1.1.1 Non-text Content
|
|
194
|
+
Fix :
|
|
195
|
+
Icon(
|
|
196
|
+
imageVector = Icons.Default.Delete,
|
|
197
|
+
contentDescription = "Delete ${task.title}" // task-specific, action-oriented
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
[HIGH] Touch target too small (24.dp × 24.dp)
|
|
201
|
+
Element : IconButton — Modifier.size(24.dp)
|
|
202
|
+
Problem : 24 dp is half the Android minimum interactive size of 48×48 dp.
|
|
203
|
+
Users with motor impairments or large fingers will frequently miss this target.
|
|
204
|
+
WCAG : 2.5.5 Target Size (Enhanced)
|
|
205
|
+
Fix :
|
|
206
|
+
IconButton(
|
|
207
|
+
onClick = { onDelete(task.id) },
|
|
208
|
+
modifier = Modifier.size(48.dp) // minimum interactive size
|
|
209
|
+
) {
|
|
210
|
+
Icon(Icons.Default.Delete, contentDescription = "Delete ${task.title}")
|
|
211
|
+
}
|
|
212
|
+
// Or keep the visual 24dp icon but expand the tap area:
|
|
213
|
+
// Modifier.size(48.dp).wrapContentSize(Alignment.Center)
|
|
214
|
+
|
|
215
|
+
[MEDIUM] Checkbox missing associated label for screen readers
|
|
216
|
+
Element : Checkbox — onCheckedChange toggles task.isDone
|
|
217
|
+
Problem : TalkBack announces "Checkbox, not checked" with no context about which task
|
|
218
|
+
this checkbox belongs to. Users navigating by touch must guess which task
|
|
219
|
+
the checkbox applies to.
|
|
220
|
+
WCAG : 4.1.2 Name, Role, Value
|
|
221
|
+
Fix :
|
|
222
|
+
Checkbox(
|
|
223
|
+
checked = task.isDone,
|
|
224
|
+
onCheckedChange = { onToggle(task.id) },
|
|
225
|
+
modifier = Modifier.semantics {
|
|
226
|
+
contentDescription = "${if (task.isDone) "Mark incomplete" else "Mark complete"}: ${task.title}"
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
// Or merge the Row into a single accessible node:
|
|
230
|
+
Row(
|
|
231
|
+
modifier = Modifier
|
|
232
|
+
.fillMaxWidth()
|
|
233
|
+
.padding(16.dp)
|
|
234
|
+
.semantics(mergeDescendants = true) {} // merges Checkbox + Text into one node
|
|
235
|
+
.toggleable(
|
|
236
|
+
value = task.isDone,
|
|
237
|
+
onValueChange = { onToggle(task.id) },
|
|
238
|
+
role = Role.Checkbox
|
|
239
|
+
)
|
|
240
|
+
) { ... }
|
|
241
|
+
|
|
242
|
+
SCREEN READER ASSESSMENT
|
|
243
|
+
-------------------------
|
|
244
|
+
TalkBack / VoiceOver compatibility: FAIL
|
|
245
|
+
→ TalkBack users encounter: an unlabeled delete button (cannot identify function),
|
|
246
|
+
a sub-minimum tap target (likely to miss), and a checkbox with no task context.
|
|
247
|
+
A blind user cannot safely operate this component.
|
|
248
|
+
|
|
249
|
+
TOUCH TARGET AUDIT
|
|
250
|
+
------------------
|
|
251
|
+
All targets ≥48dp: No
|
|
252
|
+
→ IconButton is 24×24 dp — fails Android minimum (48×48 dp).
|
|
253
|
+
|
|
254
|
+
DYNAMIC CONTENT
|
|
255
|
+
---------------
|
|
256
|
+
State changes announced: N/A
|
|
257
|
+
→ No dynamic content changes (snackbars, badges) in this component.
|
|
258
|
+
|
|
259
|
+
OVERALL VERDICT: INACCESSIBLE
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Notes
|
|
265
|
+
|
|
266
|
+
- The agent cannot verify color contrast ratios from source code alone. Test contrast with the Android Accessibility Scanner or iOS Accessibility Inspector.
|
|
267
|
+
- Always test with real assistive technology on a physical device — TalkBack on Android, VoiceOver on iOS — emulator behavior differs.
|
|
268
|
+
- Tested with: Claude Sonnet 4.6, GPT-4o.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Example Input — Accessibility Auditor
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
PLATFORM: Android-Compose
|
|
7
|
+
FILE_PATH: ui/components/TaskItem.kt
|
|
8
|
+
CODE:
|
|
9
|
+
@Composable
|
|
10
|
+
fun TaskItem(
|
|
11
|
+
task: Task,
|
|
12
|
+
onDelete: (String) -> Unit,
|
|
13
|
+
onToggle: (String) -> Unit
|
|
14
|
+
) {
|
|
15
|
+
Row(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
|
|
16
|
+
Checkbox(
|
|
17
|
+
checked = task.isDone,
|
|
18
|
+
onCheckedChange = { onToggle(task.id) }
|
|
19
|
+
)
|
|
20
|
+
Text(
|
|
21
|
+
text = task.title,
|
|
22
|
+
modifier = Modifier.weight(1f)
|
|
23
|
+
)
|
|
24
|
+
IconButton(
|
|
25
|
+
onClick = { onDelete(task.id) },
|
|
26
|
+
modifier = Modifier.size(24.dp)
|
|
27
|
+
) {
|
|
28
|
+
Icon(Icons.Default.Delete, contentDescription = null)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## What to Expect
|
|
37
|
+
|
|
38
|
+
The agent identifies three accessibility issues. See [`example-output.md`](example-output.md) for the full WCAG-annotated report.
|
|
39
|
+
|
|
40
|
+
**Issue map:**
|
|
41
|
+
1. Delete `IconButton` has no `contentDescription` — TalkBack announces "button" with no context (CRITICAL)
|
|
42
|
+
2. `IconButton` is 24×24dp — below the 48×48dp Android minimum (HIGH)
|
|
43
|
+
3. `Checkbox` has no associated label — TalkBack announces "Checkbox, not checked" with no task context (MEDIUM)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Variations
|
|
48
|
+
|
|
49
|
+
### iOS SwiftUI
|
|
50
|
+
```
|
|
51
|
+
PLATFORM: iOS-SwiftUI
|
|
52
|
+
FILE_PATH: Views/TaskRowView.swift
|
|
53
|
+
CODE:
|
|
54
|
+
struct TaskRowView: View {
|
|
55
|
+
let task: Task
|
|
56
|
+
let onDelete: () -> Void
|
|
57
|
+
let onToggle: () -> Void
|
|
58
|
+
var body: some View {
|
|
59
|
+
HStack {
|
|
60
|
+
Image(systemName: task.isDone ? "checkmark.circle.fill" : "circle")
|
|
61
|
+
.onTapGesture { onToggle() }
|
|
62
|
+
Text(task.title)
|
|
63
|
+
Spacer()
|
|
64
|
+
Button(action: onDelete) {
|
|
65
|
+
Image(systemName: "trash")
|
|
66
|
+
}
|
|
67
|
+
.frame(width: 20, height: 20)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### React Native
|
|
74
|
+
```
|
|
75
|
+
PLATFORM: React-Native
|
|
76
|
+
FILE_PATH: src/components/NotificationBadge.tsx
|
|
77
|
+
CODE:
|
|
78
|
+
const NotificationBadge = ({ count }: { count: number }) => (
|
|
79
|
+
<View style={styles.badge}>
|
|
80
|
+
<Text style={styles.count}>{count}</Text>
|
|
81
|
+
</View>
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
Issue: Badge updates are not announced to screen readers — when count changes, TalkBack/VoiceOver users don't know.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Example Output — Accessibility Auditor
|
|
2
|
+
|
|
3
|
+
Full agent response to the input in [`example-input.md`](example-input.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
ACCESSIBILITY AUDIT
|
|
9
|
+
===================
|
|
10
|
+
File: ui/components/TaskItem.kt
|
|
11
|
+
Platform: Android-Compose
|
|
12
|
+
Issues Found: 3
|
|
13
|
+
Critical: 1 High: 1 Medium: 1 Low: 0
|
|
14
|
+
|
|
15
|
+
FINDINGS
|
|
16
|
+
--------
|
|
17
|
+
|
|
18
|
+
[CRITICAL] Icon button has no accessibility label
|
|
19
|
+
Element : IconButton → Icon(Icons.Default.Delete, contentDescription = null)
|
|
20
|
+
TalkBack announces: "Button" (no function description)
|
|
21
|
+
Should announce : "Delete [task title]"
|
|
22
|
+
WCAG : 1.1.1 Non-text Content
|
|
23
|
+
Problem : contentDescription = null means TalkBack announces this as an unlabeled
|
|
24
|
+
interactive button. Screen reader users cannot know what tapping it does
|
|
25
|
+
without trial and error — a potentially destructive action with no label is
|
|
26
|
+
unusable for visually impaired users.
|
|
27
|
+
Fix :
|
|
28
|
+
IconButton(
|
|
29
|
+
onClick = { onDelete(task.id) },
|
|
30
|
+
modifier = Modifier.size(48.dp) // also fix touch target — see HIGH finding
|
|
31
|
+
) {
|
|
32
|
+
Icon(
|
|
33
|
+
imageVector = Icons.Default.Delete,
|
|
34
|
+
// Action-oriented, task-specific — not "Trash icon" or "Delete"
|
|
35
|
+
contentDescription = "Delete ${task.title}"
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[HIGH] Touch target too small (24×24 dp)
|
|
40
|
+
Element : IconButton with Modifier.size(24.dp)
|
|
41
|
+
WCAG : 2.5.5 Target Size (Enhanced) — minimum 44×44 CSS px; Android guideline: 48×48 dp
|
|
42
|
+
Problem : 24dp is half the Android minimum interactive size. Users with motor impairments,
|
|
43
|
+
tremors, or large fingers will frequently miss this target. On high-density
|
|
44
|
+
displays, 24dp is physically very small — typically 6–8mm on a phone screen.
|
|
45
|
+
Fix :
|
|
46
|
+
IconButton(
|
|
47
|
+
onClick = { onDelete(task.id) },
|
|
48
|
+
modifier = Modifier.size(48.dp) // meets the 48×48dp minimum
|
|
49
|
+
) {
|
|
50
|
+
Icon(
|
|
51
|
+
imageVector = Icons.Default.Delete,
|
|
52
|
+
contentDescription = "Delete ${task.title}",
|
|
53
|
+
modifier = Modifier.size(24.dp) // keep icon visually 24dp inside the 48dp target
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
Alternative: use Modifier.minimumInteractiveComponentSize() which enforces the platform
|
|
57
|
+
minimum automatically:
|
|
58
|
+
IconButton(
|
|
59
|
+
onClick = { onDelete(task.id) },
|
|
60
|
+
modifier = Modifier.minimumInteractiveComponentSize()
|
|
61
|
+
) { ... }
|
|
62
|
+
|
|
63
|
+
[MEDIUM] Checkbox missing task context label
|
|
64
|
+
Element : Checkbox — checked = task.isDone, onCheckedChange = { onToggle(task.id) }
|
|
65
|
+
TalkBack announces: "Checkbox, not checked" (no task name)
|
|
66
|
+
Should announce : "Mark complete: Buy groceries, Checkbox, not checked"
|
|
67
|
+
WCAG : 4.1.2 Name, Role, Value
|
|
68
|
+
Problem : TalkBack reads the Checkbox with its checked/unchecked state but no context
|
|
69
|
+
about which task it belongs to. A user navigating by touch exploration must
|
|
70
|
+
guess which checkbox belongs to which task.
|
|
71
|
+
Fix Option A — add semantics to the Checkbox:
|
|
72
|
+
Checkbox(
|
|
73
|
+
checked = task.isDone,
|
|
74
|
+
onCheckedChange = { onToggle(task.id) },
|
|
75
|
+
modifier = Modifier.semantics {
|
|
76
|
+
contentDescription = "${if (task.isDone) "Mark incomplete" else "Mark complete"}: ${task.title}"
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
Fix Option B — merge the Row into one accessible element (better UX):
|
|
81
|
+
Row(
|
|
82
|
+
modifier = Modifier
|
|
83
|
+
.fillMaxWidth()
|
|
84
|
+
.padding(16.dp)
|
|
85
|
+
// Merge all child semantics into one accessible node
|
|
86
|
+
.semantics(mergeDescendants = true) {}
|
|
87
|
+
// Make the whole row toggleable as a checkbox
|
|
88
|
+
.toggleable(
|
|
89
|
+
value = task.isDone,
|
|
90
|
+
onValueChange = { onToggle(task.id) },
|
|
91
|
+
role = Role.Checkbox
|
|
92
|
+
)
|
|
93
|
+
) {
|
|
94
|
+
// Remove individual Checkbox onCheckedChange — the Row handles interaction
|
|
95
|
+
Checkbox(checked = task.isDone, onCheckedChange = null)
|
|
96
|
+
Text(text = task.title, modifier = Modifier.weight(1f))
|
|
97
|
+
// Delete button — keep separate from the toggleable Row
|
|
98
|
+
IconButton(
|
|
99
|
+
onClick = { onDelete(task.id) },
|
|
100
|
+
modifier = Modifier.minimumInteractiveComponentSize()
|
|
101
|
+
) {
|
|
102
|
+
Icon(Icons.Default.Delete, contentDescription = "Delete ${task.title}")
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
With Option B, TalkBack reads the entire row as: "Buy groceries, not checked, Checkbox"
|
|
106
|
+
and tapping anywhere on the row toggles the task — much more usable.
|
|
107
|
+
|
|
108
|
+
SCREEN READER ASSESSMENT
|
|
109
|
+
-------------------------
|
|
110
|
+
TalkBack / VoiceOver compatibility: FAIL
|
|
111
|
+
→ A visually impaired user encounters:
|
|
112
|
+
- An unlabeled delete button (cannot identify what it does)
|
|
113
|
+
- A 24dp tap target (likely to miss with assistive touch or motor impairment)
|
|
114
|
+
- A checkbox with no task context (cannot know which task they're checking)
|
|
115
|
+
The component is not safely operable with TalkBack enabled.
|
|
116
|
+
|
|
117
|
+
TOUCH TARGET AUDIT
|
|
118
|
+
------------------
|
|
119
|
+
All targets ≥ 48dp: No
|
|
120
|
+
→ IconButton is 24×24dp — fails Android guideline.
|
|
121
|
+
→ Checkbox is full-height (inherits Row padding) — acceptable. ✓
|
|
122
|
+
→ Text is not interactive — not evaluated. ✓
|
|
123
|
+
|
|
124
|
+
DYNAMIC CONTENT
|
|
125
|
+
---------------
|
|
126
|
+
State changes announced: N/A
|
|
127
|
+
→ No async state changes (snackbars, counters) in this component.
|
|
128
|
+
→ If task completion triggers a Snackbar elsewhere in the tree, ensure it uses
|
|
129
|
+
Modifier.semantics { liveRegion = LiveRegionMode.Polite } to announce to TalkBack.
|
|
130
|
+
|
|
131
|
+
OVERALL VERDICT: INACCESSIBLE
|
|
132
|
+
```
|