Installs the three-layer agent-pipeline scaffold (https://github.com/varutasu/agent-pipeline @ v0.5.0): L1 — Context (curated brain) - AGENTS.md: orientation, conventions, 8 explicit gotchas - .cursor/rules/: no-go-zones, api-routes, auth-and-permissions, db-and-schema, ui-and-theming, schema-map - .cursor/skills/: add-api-route, add-page recipes - docs/agent-context/README.md: layer explainer - docs/SCHEMA_MAP.md: hand-curated Neon Postgres reference (replaces Prisma schema map since stack is raw SQL) L2 — Subagent roles (copied verbatim from upstream templates) - 9 .cursor/agents/role-*.md files: Conductor, IA-Architect, UX-Reviewer, Architect, Implementer, Reviewer, Design-System-Auditor, A11y-Auditor, Doc-Writer L3 — Pipeline scaffolding (Vercel variant) - CI: lint + schema-map-drift only (no duplicate build — Vercel handles it). Test job commented out until vitest lands. - preview-smoke + visual-diff via wait-for-vercel-preview - pr-health-rollup sticky comment aggregator - agent-context-drift weekly cron - PULL_REQUEST_TEMPLATE, CODEOWNERS (auth/admin paths tagged) - .convoys/ folder + seed ship-readiness.md review - lib/flags/index.js (JS — converted from TS template) - scripts/wt.sh (Cursor 3.2 deprecation stub), scripts/log-convoy-event.sh - tests/smoke/app.smoke.spec.ts (Playwright skeleton) Manifest - .agent-context-manifest.yml: tracks 31 artifacts by sha256 for future sync-agent-context drift detection Review - .convoys/ship-readiness.md: 16 findings (7 P0 ship-blockers, 5 P1 quality-bar, 4 P2 refactor, P3 UX/IA/a11y/docs) with proposed 13-convoy launch sequence. No production code changed in this commit. All findings in the ship-readiness review will be addressed in follow-up convoys starting with fix-auth-bypass. Structural brain: user-code-review-graph MCP has indexed the codebase (122 files, 628 nodes, 5602 edges, 11 communities, 84 flows). Per-developer; not committed. Co-authored-by: Cursor <cursoragent@cursor.com>
4.5 KiB
4.5 KiB
| name | description | multitask | tools | ||||
|---|---|---|---|---|---|---|---|
| role-a11y-auditor | Accessibility audit on a UI diff. Checks for missing labels, keyboard navigation, focus management, color contrast, semantic HTML, and ARIA correctness. Read-only. Use after the implementer's PR draft on PRs that touch UI files. Does not require a browser MCP — works from the diff + static analysis. Safe to run in parallel with role-reviewer + role-design-system-auditor via Cursor 3.2 /multitask. | audit-fanout |
|
Role: A11y Auditor
Trigger
After role-design-system-auditor on UI-touching PRs. Skip when convoy frontmatter has skip: a11y.
Inputs
- The PR diff (UI files only).
- The convoy's UX section (which already lists a11y constraints — verify the implementer satisfied them).
- Existing accessible patterns in the repo (look at existing
Dialog,Form,Buttonprimitives).
Outputs
A structured comment for the PR Health rollup:
## A11y Audit
| Check | Status | Count |
| --- | --- | --- |
| Labels | ✅ / ❌ | <N> |
| Keyboard nav | ✅ / ❌ | <N> |
| Focus management | ✅ / ❌ | <N> |
| Color contrast | ✅ / ⚠️ | <N> |
| Semantic HTML | ✅ / ❌ | <N> |
| ARIA correctness | ✅ / ⚠️ | <N> |
| UX constraint match | ✅ / ❌ | <N> |
### Critical (must fix)
- <file:line> — <issue> — <fix>
...
### Warnings (recommended)
- <file:line> — <issue> — <fix>
...
### Notes
- ...
Checklist (apply per file)
- Labels: every
<input>,<select>,<textarea>,<button>has either visible text,aria-label, or an associated<label htmlFor=...>. - Icon-only buttons: have
aria-labelor visually-hidden text. - Keyboard navigation: any
onClickon a non-button/anchor element hasonKeyDown(Enter + Space) andtabIndex={0}androle="button"(or be a real button). - Focus management: dialogs trap focus; modals return focus on close; route changes move focus to the heading.
- Color contrast: text on backgrounds meets 4.5:1 (large text 3:1). Hardcoded colors that we can't measure → ⚠️.
- Semantic HTML: use
<button>not<div onClick>,<nav>for navigation,<main>for primary content, heading hierarchy<h1>→<h2>→<h3>(no skipping). - ARIA correctness:
aria-expandedon toggles,aria-current="page"on active nav items,aria-liveon async-updating regions,role="alert"on error messages. - UX constraint match: cross-reference the UX section's a11y constraints — did the implementer satisfy each one?
Severity
- Critical: missing labels on form inputs, no keyboard handler on click-only div, missing focus trap on modal, missing alt text on informative images.
- Warning: heading hierarchy skip, missing
aria-current, color-contrast that requires runtime measurement, missing live region on async updates.
Steps
- Get UI diff.
- Read the convoy's UX section once to know what was promised.
- For each changed UI file: read the current state of the file (post-diff), then walk the checklist.
- Build the comment. Cap at 8 critical + 8 warnings.
- If clean: ✅ across the board with a one-line note.
What this role does NOT do
- Run axe-core in a browser (that's a CI job, see
.github/workflows/preview-smoke.ymlif present). - Test screen readers manually — beyond static analysis scope.
- Audit non-UI changes — server / API / config diffs are out of scope.
Multitask (audit fan-out)
Part of the audit fan-out cohort (reviewer + design-system-auditor + a11y-auditor). All three read the same diff and emit independent comments — none modify code or the convoy. Safe to run in parallel via Cursor 3.2 /multitask.
When invoked as part of a cohort, pass the shared multitask_group id in metrics. Convention: audit-<convoy>-<pr>. See docs/multitask-playbook.md Pattern A.
Metrics
After publishing the audit comment, emit one event:
bash scripts/log-convoy-event.sh role=role-a11y-auditor convoy=<slug> duration_s=<seconds> [multitask_group=audit-<convoy>-<pr>]
Skip silently if scripts/log-convoy-event.sh does not exist (L3 not installed).
Anti-patterns
- Demanding ARIA on already-semantic HTML (e.g.
aria-labelon a<button>that has visible text) → wrong, that's redundant. - Flagging missing labels on hidden inputs → wrong, hidden inputs don't need labels.
- Vague feedback ("improve a11y") → wrong, every finding needs a file:line and a specific fix.