Communitygithub.com

Tend A11y

로컬에서 주문형으로 SvelteKit + TypeScript 저장소의 접근성, UX, 카피 톤 이슈를 한 번 실행에 하나씩 찾아내고 최소한으로 수정한 뒤 검증합니다.

Tend A11y란 무엇인가요?

Tend A11y는 SvelteKit + TypeScript 기반 저장소에서 가장 높은 우선순위의 접근성, UX, 또는 카피 톤 이슈를 한 번에 하나씩 찾아내고 최소한으로 수정한 뒤 검증하여 검토용 diff를 제공하는 AI 에이전트 스킬입니다. Claude Code, Cursor, Codex 등 주요 AI 코딩 도구에서 사용할 수 있으며, `.claude/tend/config.yaml` 설정 파일을 통해 제외 경로와 참고 노트를 관리합니다. 이 스킬은 설정이 없어도 SvelteKit + TypeScript 환경에 대한 기본 가정으로 동작하며, 저장소의 컴포넌트 라이브러리 사용 패턴을 학습한 후 정해진 우선순위(원시 HTML 대신 컴포넌트 라이브러리 사용 여부, 접근 가능한 이름 누락, 이미지 대체 텍스트, 폼 레이블, 키보드 핸들러, 비동기 피드백 알림, 파괴적 동작 확인 절차, 카피 톤)에 따라 스캔합니다. 단 한 번에 하나의 이슈만 수정하며, 기존 컴포넌트 라이브러리가 있으면 이를 활용하고, 설정된 제외 경로나 백엔드/API 로직은 절대 건드리지 않습니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add robcsaszar/tend

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Tend A11y — the herald

이 저장소의 마크업에서 가장 높은 우선순위의 접근성, UX, 또는 카피 톤 이슈를 하나 찾아내고, 최소한으로 수정한 후 검증하여 검토용 diff를 제시합니다. 한 번 실행에 하나의 이슈만 처리합니다.

0. 설정 로드

  • .claude/tend/config.yaml을 읽습니다. skills.a11y (제외 경로(globs), notes)를 사용합니다. 이 스킬은 기능 모듈(capability modules)이 없습니다. 모듈 게이팅 단계를 완전히 건너뛰며, 여기에는 modules: 게이팅 단계가 없습니다.
  • 설정이 없나요? 코어 티어로 실행합니다: 코어 SvelteKit + TS 가정, 보수적인 내장 제외 경로(절대 lockfiles, CI, .env, 설정을 건드리지 않음). 한 번 출력: "tend-onboard를 실행하면 설정이 선명해집니다." 계속 진행합니다.

1. 분류

references/scan-core.md를 반드시 읽으세요.

  • 제외 경로 집합을 설정합니다: 설정의 skills.a11y.off-limits + 내장 레일(절대 lockfiles, CI 설정, .env, 프로젝트 설정, 또는 백엔드/API 라우트 로직을 건드리지 않음 — 이 스킬은 프레젠테이션 전용입니다).
  • 진입점을 설정합니다: 이 저장소의 마크업 파일 — .svelte 컴포넌트, +page.svelte / +layout.svelte 라우트, 또는 스택이 실제로 사용하는 템플릿 파일. skills.a11y.notes에서 명명된 컴포넌트 라이브러리 디렉토리(예: src/lib/components/ui)를 확인합니다. 있다면, 해당 디렉토리의 내보내기(export)가 2단계에서 "원시 HTML 대신 사용할 대상" 목록이 됩니다.
  • 스캔하기 전에 기존 컴포넌트 1-2개를 읽어 저장소의 실제 컴포넌트 라이브러리 및 상태/로딩 관례를 학습합니다. 실제 패턴을 파악한 후에야 그 패턴에서 벗어난 것을 위반 사항으로 부를 수 있습니다.

완료 기준: 제외 경로 집합 파악, 컴포넌트 라이브러리 관례(있는 경우) 식별, 진입점 글로브(glob) 식별.

2. 스캔 — 우선순위 순서, 첫 번째 실제 적중에서 멈춤

가장 가치가 높은(사용자에게 가장 조용한) 순서대로 정렬 — 첫 번째 실제 증거 기반 적중에서 멈춥니다:

  1. 컴포넌트 라이브러리 대체제가 존재하는 원시 대화형 HTML — 저장소 다른 곳에 Button/Link/Input 내보내기가 있음에도 원시 <button>/<a>/<input>가 있는 경우.
  2. 아이콘 전용 또는 아이콘 우선 대화형 요소에 접근 가능한 이름이 누락된 경우 — aria-label, 시각적으로 숨겨진 텍스트, title 폴백이 없음.
  3. alt가 없는 <img> — 속성 누락이 위반 사항입니다. 장식용 이미지에 의도적인 빈 alt=""는 위반이 아닙니다.
  4. 연결된 레이블이 없는 폼 입력 — label for=, aria-label, 또는 컴포넌트 라이브러리 레이블 prop이 없음. 템플릿뿐만 아니라 렌더링된 개수도 감사합니다: 루프({#each} 또는 동등 구문) 안에서 생성된 입력은 런타임에 N개의 익명 컨트롤을 생성합니다.
  5. role="button" (또는 비대화형 요소의 onclick)에 연결된 키보드 핸들러가 누락된 경우 — Enter + Space에 대한 onkeydown. 네이티브 <button>은 이를 자동으로 얻습니다. 이는 원시 요소 이스케이프 해치에서만 발생합니다.
  6. 비동기 성공/오류/로딩 피드백이 평범하고 공개되지 않은 요소로 렌더링된 경우 — role="alert"/role="status", aria-live, 또는 저장소 다른 곳에서 이미 사용 중인 기존 컴포넌트 라이브러리 배너/토스트 기본 요소가 없음.
  7. 파괴적 작업(삭제/제거/재설정)이 적용되기 전에 확인 단계가 없는 경우.
  8. 카피 톤 위반, 설정 기반 허용/거부 목록(skills.a11y.notes, 또는 그 목록이 가리키는 프로젝트 톤 문서)에 대해 확인. 저장소별 목록이 없으면, 일반 기본값으로 폴백: 검증/오류 지시 앞에 명령형 완화어 "Please"(예: "Enter a name" 대신 "Please enter a name"), 또는 일상적인 확인/안내 카피에 불필요한 느낌표 사용. 렌더링된 마크업 텍스트와 <script> 블록 내의 문자열 리터럴 모두를 스캔 — 변수에 할당된 카피, toast/alert 호출에 전달된 카피, 또는 .textContent/.innerText를 통해 설정된 카피는 마크업이 아닌 스크립트 블록에 존재하며, 마크업 전용 grep은 실제 검증 문자열을 놓칩니다.

3. 수정 — 하나의 원자적 변경

편집 전에 다음 질문에 답하세요:

  1. 이것이 실제 사용자(스크린 리더, 키보드 전용 사용자, 또는 톤을 읽는 사람)에게 진정으로 불명확하거나 접근 불가능한가? — 내 개인적 스타일 선호도가 아닌가?
  2. 수정이 프레젠테이션/카피에만 영향을 미치는가? — 로직, 백엔드, 새 종속성은 건드리지 않는가?
  3. 이 패턴에 대한 컴포넌트 라이브러리 대체제가 이미 존재하는가? 존재한다면, 원시 HTML 수정을 직접 만드는 대신 그것을 사용하라(저장소에 이미 role="alert"를 포함하는 상태/배너 컴포넌트가 있다면 원시 <div>에 role="alert"를 덧붙이지 마라).

기본 검증: 편집 전에 저장소의 린트/타입체크(그리고 빠르다면 테스트 스위트)를 실행 — 나중에 잘못 귀속시키지 않도록 기존 실패를 기록해 둡니다.

크기 예산: 마크업/구조 수정 시 변경 줄 ≤50줄, 순수 카피 텍스트 수정 시 ≤10줄; 한 번 실행에 하나의 컴포넌트 또는 페이지.

절대 제외 경로를 건드리지 마십시오. 실제 수정이 제외 경로를 건드려야 한다면, 중단하고 다른 곳에서 강제로 처리하는 대신 그 이유를 보고하십시오.

4. 검증 및 제시

린트/타입체크(그리고 3단계에서 테스트를 실행했다면 테스트도)를 다시 실행 — 자신의 변경이 새로운 실패를 도입한 경우에만 중단합니다. 기존 실패는 여기서 수정할 대상이 아닙니다. diff를 보여줍니다. 중단 — 커밋하지 말고, PR을 열지 마십시오.

절대 하지 말 것

  • 절대 한 번 실행에 하나 이상의 이슈를 표시하거나 수정하지 마십시오 대신: 첫 번째 실제 적중에서 스캔을 멈추고, 수정한 후 제시하십시오. 이유: 일괄 처리된 접근성/카피 diff는 개별적으로 검토하기 어렵고, 어떤 특정 수정이 회귀를 일으켰는지 숨깁니다.

  • 절대 컴포넌트 라이브러리 대체제가 이미 존재하는데 원시 HTML 수정을 직접 만들지 마십시오 대신: 저장소 자체의 Button/Input/Link/상태 배너 컴포넌트를 사용하십시오. 이유: 병렬적인 일회성 수정은 저장소의 나머지 부분이 이미 의존하는 하나의 패턴으로 수렴하는 대신 두 번째 불일치 패턴을 만듭니다. 다음 감사에서 표류(drift)로 다시 플래그될 것입니다.

  • 절대 skills.a11y.notes나 일반적이고 명확하게 레이블된 기본값에 의해 뒷받침되지 않는 카피 톤 규칙을 발명하지 마십시오 대신: 설정 기반 허용/거부 목록을 사용하거나, 명시적으로 일반 기본 패턴으로 폴백하고 있음을 밝히십시오. 이유: 즉석에서 발명된 규칙은 다음 실행에서 재사용 가능하거나 감사 가능하지 않으며, 저장소의 실제 하우스 스타일과 모순될 수 있습니다.

  • 절대 마크업만 스캔하고 카피 문자열을 위해 <script> 블록을 건너뛰지 마십시오 대신: <script> 블록 내의 문자열 리터럴도 grep하십시오 — 검증 및 피드백 카피는 종종 템플릿에 직접 작성되지 않고 변수에 할당됩니다. 이유: 실제 사용자 대상 문자열은 종종 템플릿에 보간된 변수입니다. 마크업 전용 grep은 보간 지점만 일치시키고 실제 문제가 되는 텍스트는 일치시키지 않아 수정할 내용을 보고하지 않습니다.

  • 절대 제외 경로를 건드리거나 커밋/PR을 열지 마십시오 대신: skills.a11y.off-limits와 내장 레일을 존중하고, diff를 제시한 후 중단하십시오. 이유: 이 스킬의 작업은 "검증된 diff, 사람 검토 준비 완료"에서 끝납니다. 커밋하거나 제외된 경로를 건드리면 전체 워크플로가 의존하는 검토 게이트가 제거됩니다.

파일

  • references/scan-core.md — 핵심 검사 (1단계에서 로드됨)
  • evals/ — ai-forge-eval 어설션

관련 스킬