Tend A11y — 传令官
查找此仓库标记中单个最高优先级的无障碍、用户体验或文案语气问题,以最小化方式修复、验证,并将差异交回审查。每次运行仅处理一个问题。
0. 加载配置
- 读取
.claude/tend/config.yaml。使用skills.a11y(禁止修改的文件列表、说明)。本技能没有功能模块——完全跳过模块门控步骤,此处没有modules:门控步骤。 - 没有配置? 按照核心层级运行:核心 SvelteKit + TS 假设,保守的内置防护规则(绝不碰锁文件、CI、
.env、配置)。输出一次:“运行tend-onboard以优化。”然后继续。
1. 初步评估
必须阅读 references/scan-core.md。
- 确定禁止修改的文件集合:配置中的
skills.a11y.off-limits加上内置防护规则(绝不碰锁文件、CI 配置、.env、项目配置或后端/API 路由逻辑——此技能仅处理表示层)。 - 确定入口点:此仓库的标记文件——
.svelte组件、+page.svelte/+layout.svelte路由,或堆栈实际使用的任何模板文件。检查skills.a11y.notes中是否有命名的组件库目录(例如src/lib/components/ui)——如果存在,其导出将是第 2 阶段的“使用此替代原始 HTML”目标列表。 - 在扫描之前,先阅读 1-2 个现有组件,以了解仓库实际的组件库和状态/加载约定——你需要先掌握真实模式,才能将偏离它的行为视为违规。
完成标准:已知禁止修改的文件集合,已识别组件库约定(如果有),已识别入口点 glob 模式。
2. 扫描——按优先级顺序,在第一个真实命中处停止
按最高价值(对用户最无声)排序——在第一个有证据支持的真实命中处停止:
- 原始交互式 HTML,但仓库中存在组件库等效替代品——仓库其他位置存在
Button/Link/Input导出,却使用原始<button>/<a>/<input>。 - 仅图标或图标为主的交互元素缺少可访问名称——没有
aria-label,没有视觉隐藏文本,没有title后备。 <img>缺少alt——缺少属性是违规;用于装饰性图像的刻意空alt=""不是违规。- 表单输入没有关联标签——没有
label for=、aria-label或组件库标签属性。审计渲染后的数量,而不仅仅是模板:在循环({#each}或等效)内生成的输入在运行时产生 N 个匿名控件。 role="button"(或非交互元素上使用裸onclick)缺少配对的键盘处理程序——缺少 Enter + Space 的onkeydown。原生<button>自带此功能;此规则仅针对使用原始元素转义的情况。- 异步成功/错误/加载反馈以普通、无声明的元素呈现——没有
role="alert"/role="status",没有aria-live,并且仓库其他位置没有已使用的现有组件库横幅/提示框原语。 - 破坏性操作(删除/移除/重置)在没有确认步骤的情况下生效。
- 文案语气违规,根据配置驱动的允许/拒绝列表(
skills.a11y.notes,或它指向的项目语气文档)进行检查。如果不存在仓库特定的列表,则回退到通用默认值:在验证/错误指令前使用强制软化词如“请”(“请输入名称” vs “输入名称”),或在常规确认/说明文案中使用不必要的感叹号。扫描渲染后的标记文本和<script>块内的字符串字面量——分配给变量、传递给 toast/alert 调用或通过.textContent/.innerText设置的文案存储在脚本块中,而不仅仅是标记中,仅扫描标记的 grep 会错过真实的验证字符串。
3. 修复——一次原子更改
在编辑之前,回答以下问题:
- 这对真实用户(屏幕阅读器、纯键盘用户或阅读语气的用户)来说,是否真的不清楚或不可访问——而不是我个人的风格偏好?
- 修复是否仅涉及表示层/文案——没有逻辑、没有后端、没有新依赖?
- 此模式是否已存在组件库等效替代品?如果是,则使用它而不是手动编写原始 HTML 修复(如果仓库已经有一个携带
role="alert"的状态/横幅组件,则不要将role="alert"硬塞到原始<div>上)。
基线验证:在编辑前运行仓库的 lint/类型检查(如果快速,则运行测试套件)——注意任何预先存在的失败,以免后来错误地归因。
大小预算:标记/结构性修复不超过 50 行更改,纯文案修复不超过 10 行;每次运行一个组件或页面。
绝不碰禁止修改的路径。如果实际修复需要触碰其中一个,则停止并报告原因,而不是强行在其他地方实现。
4. 验证并呈现
重新运行 lint/类型检查(以及测试,如果你在第 3 步中运行了它们)——仅当你的更改引入新失败时才中止;预先存在的失败不是你来修复的。显示差异。停止——不要提交,不要打开拉取请求。
切勿
-
切勿标记或修复每次运行超过一个问题 应改为: 在第一个真实命中处停止扫描,修复它,呈现它。 原因: 批量处理的无障碍/文案差异难以单独审查,并且掩盖了哪个特定修复导致了回归。
-
切勿在存在组件库等效替代品时手动编写原始 HTML 修复 应改为: 使用仓库自己的
Button/Input/Link/状态横幅组件。 原因: 并行的单次修复会创造第二个不一致的模式,而不是收敛到仓库其余部分已经依赖的模式——下次审计将再次将其标记为漂移。 -
切勿发明不受
skills.a11y.notes或通用明确标记的默认值支持的文案语气规则 应改为: 使用配置驱动的允许/拒绝列表,或明确声明你正在回退到通用默认模式。 原因: 现场发明的规则在下一次运行时不可重用或不可审计,并且可能违反仓库的实际内部风格。 -
切勿仅扫描标记而跳过
<script>块中的文案字符串 应改为: 也 grep<script>块内的字符串字面量——验证和反馈文案经常在那里分配,而不是直接写在模板中。 原因: 真实面向用户的字符串通常是插值到模板中的变量;仅扫描标记的 grep 匹配的是插值位置,而不是实际的违规文本,并且报告不出任何要修复的内容。 -
切勿触碰禁止修改的路径或提交/打开拉取请求 应改为: 尊重
skills.a11y.off-limits加上内置防护规则;在呈现差异后停止。 原因: 此技能的工作结束于“已验证的差异,可供人工审查”——提交或触碰排除的路径会移除整个工作流所依赖的审查关口。
文件
references/scan-core.md——核心检查(在第 1 阶段加载)evals/——ai-forge-eval 断言