검증
테스트를 채운 다음, 그 테스트가 스펙대로 커버하는지, flaky하지 않은지, 셀렉터가 취약하지 않은지, 실키가 새지 않았는지를 한 번 묻는 자리가 필요합니다. /run-suite가 동작을 보고, /review-e2e가 정적 품질을 봅니다. 한쪽만 통과해서는 진짜 통과가 아닙니다.
| 도구 | 보는 자리 |
|---|---|
/run-suite | 동작. 선택 트랙을 실행하고 크리티컬 플로우 언어로 결과를 합성 |
/review-e2e | 정적. 6차원 루브릭으로 구조 품질을 평가 |
run-suite의 결과 합성
섹션 제목: “run-suite의 결과 합성”raw 리포터 출력은 사용자에게 그대로 가지 않습니다. e2e-spec.md §2 플로우 단위로 다시 묶입니다. 통과는 한 줄, 실패만 무엇, 어디, 추정 원인, 다음 단계를 답니다.
## 동작 검증 결과 — web
✓ 비로그인 방문자가 가격 페이지에서 Pro 결제 → 대시보드 진입✓ 로그인 사용자가 설정에서 프로필 수정✗ 로그인 사용자가 결제 관리(Customer Portal) 이동 - 위치: tests/web/specs/billing.spec.ts:42 - 메시지: customer-portal 호출이 401 - 추정 원인: Authorization 헤더 누락 또는 세션 만료 - 다음: implement-web-suite 재호출 — 세션 추출 부분 검토assertion line은 보고서 파일(run-{ISO}.md)에만 남기고, 전체 로그는 .claude/state/last-run.log에 통째로 들어갑니다. 출력이 50줄을 넘으면 컨텍스트에는 error와 warning만 흘립니다(Silence on Success).
review-e2e 6차원
섹션 제목: “review-e2e 6차원”루브릭의 SSOT는 AI_AUTOMATION.md §7입니다. 각 차원 5/3/1점이고, 통과는 모든 차원 3점 이상입니다.
| 차원 | 5점 | 1점 |
|---|---|---|
| 커버리지 | §2 크리티컬 플로우 모두 테스트 존재 | 핵심 플로우 미커버 |
| flakiness | 하드 sleep 0, 재실행 안정, retry 정책 명시 | sleep 남발, 불안정 |
| 셀렉터 품질 | role/label/testID 우선, CSS/XPath 0 | XPath와 취약 셀렉터 다수 |
| 테스트 격리 | 컨텍스트, DB, 디바이스 상태 격리, 인증만 재사용 | 순서 의존, 전역 상태 |
| 실행 성능 | 병렬과 샤딩, 합리적 시간 | 과도하게 느림, 중복 |
| 유지보수성 | POM 재사용, fixture 정리, 명확한 실패 메시지 | 로케이터 흩어짐, 읽기 어려움 |
검증자는 근거 없는 5점을 주지 않습니다(Evaluator Calibration). 의심되면 낮춰 잡고 fix suggestion을 답니다. flakiness는 grep -rn 'waitForTimeout\|sleep'로 잡고, 셀렉터 품질은 grep으로 CSS/XPath 남용을 셉니다. 결과는 차원별 점수와 근거와 함께 .claude/state/review-{ISO}.md에 한 장 떨어집니다.
금지 패턴
섹션 제목: “금지 패턴”AI_AUTOMATION.md §5가 reviewer가 차단하는 패턴을 들고 있습니다. 대부분 grep으로 잡히는 자리입니다.
| 금지 | 왜 | 대체 |
|---|---|---|
하드 sleep, waitForTimeout(n) | flaky의 1순위 원인 | auto-wait, web-first assertion, waitForResponse, idle 동기화(Detox) |
| CSS/XPath 셀렉터 남용 | DOM 변경에 취약 | getByRole → getByLabel/getByText → 최후수단 getByTestId(mobile은 testID) |
| 프로덕션 SUT, DB 접근 | 데이터 오염, 사고 | 로컬/스테이징/전용 테스트 환경(S6) |
| 웹뷰 컨텍스트 ID 하드코딩 | 실행마다 달라짐 | getContextHandles()로 조회 후 전환 |
| 브라우저 바이너리 캐싱(CI) | 버전 불일치, OS 의존성 | 매번 playwright install --with-deps |
| Electron 네이티브 UI 직접 클릭 | 자동화 불가 | 메인 프로세스 API를 evaluate/stub |
| 테스트 간 상태 공유 | 순서 의존, flaky | 테스트마다 새 컨텍스트, 인증만 storageState 재사용 |
| 실키를 spec/CI 로그에 노출 | 유출 | env와 시크릿 저장소, 마스킹(S2, S7) |
보안 기준선 S1~S8
섹션 제목: “보안 기준선 S1~S8”AI_AUTOMATION.md §4의 여덟 줄입니다. e2e 도메인에 맞춰 박힌 자리입니다.
- S1 최소 권한. 테스트 계정은 전용이고 저권한입니다. 관리자나 실사용자 계정으로 e2e를 돌리지 않습니다.
- S2 시크릿 격리. 실키와 비밀번호는 코드나 리포에 박지 않습니다.
.env.test.local(gitignored)만 쓰고, 리포에는.env.test.example의 키 목록만 둡니다. - S3 입력 검증. 외부에서 받은 SUT URL과 자격증명을 그대로 신뢰하지 않고 형식을 검증합니다.
- S4 출력 감사. trace, video, 스크린샷에 토큰이나 PII가 찍히면 마스킹합니다. 아티팩트 공개 범위를 주의합니다.
- S5 파괴적 명령 차단.
db reset이나 계정 삭제는 명시 확인 후에만. 트랙이나 디렉토리를 지우기 전에도 사용자 확인을 받습니다. - S6 환경 격리. 프로덕션 SUT와 프로덕션 DB 접근은 절대 금지입니다. 로컬, 스테이징, 전용 테스트 환경만.
- S7 로그 마스킹. 보고서와 로그에 자격증명과 세션 토큰을 노출하지 않습니다.
- S8 외부 통신 감사. 테스트가 호출하는 외부 엔드포인트를 명시하고, 실결제나 실발송 같은 부작용은 test mode로 차단합니다.
S6과 S2가 이 도메인에서 가장 먼저 차단되는 자리입니다. 프로덕션에 붙거나 실키가 새면 그 자리에서 멈춥니다.
Sprint Contract와 iteration 한계
섹션 제목: “Sprint Contract와 iteration 한계”/review-e2e가 changes_requested를 반환하면 대상 트랙과 차원을 명시하고 그 트랙의 implement-*를 재호출합니다. reviewer는 코드를 고치지 않고 builder가 그 부분만 외과적으로 수정합니다. 이 루프는 iteration 두 번까지입니다. 두 번 연속 막히면 stage가 blocked로 바뀌고 /recover-from-blocked가 트리거 자리에 들어갑니다. 비개발자 호흡으로 같은 복구 흐름을 푼 자리는 비개발자용 when-ai-gets-stuck에 있습니다.
빠른 참조
섹션 제목: “빠른 참조”/run-suite # 선택 트랙 실행 + 시나리오 언어 보고/review-e2e # 6차원 합성
PM="$(jq -r '.name' .claude/state/package-manager.json)"$PM exec playwright test --project=chromium # web 직접$PM exec playwright test --project=electron # electron 직접 (Linux 로컬은 xvfb-run 래핑)maestro test tests/mobile/flows # mobile (Maestro)다음 섹션은 ci입니다. .github/workflows/e2e.yml이 트랙별로 어떻게 갈리는지, web 샤딩과 blob 머지, electron의 Linux 전용 xvfb, mobile의 emulator와 cloud를 봅니다.