release: v0.10.0
All checks were successful
ci / build (push) Successful in 42s
release / release (push) Successful in 1m5s

This commit is contained in:
Yun Chan 2026-08-29 21:19:26 +09:00
parent 2b7fa32b5b
commit 6930906583
61 changed files with 15165 additions and 82 deletions

View file

@ -32,6 +32,9 @@
| 탭 전환 스크롤 잔류 — 짧은 뷰에서 클램프되어 헤더 반쯤 잘림, 뷰마다 크롬 위치 제각각 | 뷰 전환 `scrollTo(0,0)` 단언(M5) + mobile-app-ux.md |
| 크럼을 헤더로 내보내 빈약한 헤더 — 계측 전부 통과했지만 사용자에게 '깨져 보인다' | 헤더 sticky·브랜드+액션 구조 단언 + **시각 무게 평가(눈)** — mobile-app-ux.md |
| 왼쪽 인셋 리듬 불일치(제목 16 vs 앱바·카드 24) — 오버플로 검사는 오른쪽만 보므로 통과 | M6 왼쪽 인셋 스위트(텍스트 시작점 ≥12px·같은 축 ±10px) + preflight §0-E |
| 모바일에서 절대 배치 지도 자식의 부모를 `position: static`으로 바꿈 — offsetParent가 BODY가 되어 격자·핀이 히어로 전체를 덮음. 기하 게이트 8/8 통과 | **상태별 실제 캡처를 열어 보는 시각 E2E** + absolute/fixed 자식의 containing block 단언(하니스 규칙 19) |
| 새 관리자·가맹 서브페이지가 생겼지만 `public/work/*/index.html`만 검사 — 새 HTML 오류 8건이 검증 밖 | 정적 입력을 `public/work/**/*.html`·`**/*.css`로 재귀화 + 검사 대상 파일 수 단언(하니스 규칙 20) |
| 마케팅 h1의 의도적 2줄 때문에 범용 1줄 규칙을 꺼 버릴 위험 | 기본 1줄 유지 + 페이지별 `h1MaxLines` 계약. 375·390 × 글꼴 확대 매트릭스도 같은 상한 적용 |
## 7계층
@ -42,7 +45,7 @@
| L0 정적 | stylelint + html-validate | 문법·구문 위반을 브라우저 켜기 전에 |
| L1 단위 | 순수 계산 로직 추출(calc.js) + 경계값 테스트 | 프로젝트별 작성 — 0명/만석/초과/빈배열. **입력 검증·신청 가능 같은 '판정'(가능/불가+사유)도 여기 둔다** — UI 는 판정을 문장으로 번역만 |
| L2 불변식 | `design-gate.mjs` — 오버플로·h1·수축·대비·SEO/meta·죽은 선택자·토큰 위생·theme-color 정합 | 전 뷰 × 전 폭 |
| L3 시각 회귀 | 기준 화면 pixelmatch diff (≥0.1% 실패) | 갱신은 검증된 배포 후 `--update-baseline` |
| L3 시각 회귀 | 기준 화면 pixelmatch diff (≥0.1% 실패) + 핵심 상태 캡처 | 갱신은 검증된 배포 후 `--update-baseline`. 캡처 존재와 사람의 시각 판정은 별개다 |
| L4 WebKit | Playwright webkit | 사파리 엔진 렌더 차이 |
| L5 탐색 | 키보드 완전 통과 + 사용자 여정 차터 | 프로젝트별 작성 — 마우스 금지 |
| L6 시나리오 E2E | 실사용자 여정 재현 — 페르소나의 하루·장기 과업 포함 | 프로젝트별 작성. **기대값 단언 필수**(하니스 규칙 8), 백 키·시트·양방향 흐름은 `mobile-app-ux.md` 패턴 기준. 실측: RED 1,742 단언 중 318 실패가 신규 기능에 정확히 집중 — 시나리오를 먼저 쓰면 미구현이 수치로 드러난다 |
@ -89,6 +92,17 @@ L1·L5 는 프로젝트 안에 `tools/unit/*.test.mjs`, `tools/exploratory.mjs`
15. **시각 기준 갱신은 의도 변경 리뷰를 동반한다** — "달라졌으니 갱신"으로 결함이 기준에 박힌다(실측: 왼쪽 인셋 결함 화면이 기준 갱신으로 '정상'이 되어 재발을 숨겼다). 갱신 전에 무엇이 의도적으로 바뀌었는지 한 줄씩 나열하고, 사용자 보고가 있던 화면은 수리 후 재촬영한다.
16. **사용자 보고 스크린샷은 비전 요약이 아니라 픽셀 판정으로 해부한다** — 비전 모델의 픽셀 추정("~0px", "~16px")은 부정확하다. pngjs 등으로 화면을 가로 밴드로 나눠 각 밴드의 텍스트 시작 x를 직접 재면(보임 행만, 왼쪽 테두리 아티팩트 제외) "무엇이 어디서 어긋났는지"가 수치로 나온다. 실측: '제목이 가장자리에 붙는다'는 보고가 앱바 24px·제목 16px의 리듬 불일치로 확정됐다.
17. **새 검사는 수정 전 코드로 RED 재현 후 GREEN** — 검사 자체의 측정 하자(오탐)도 이렇게 잡는다. 실측: 왼쪽 인셋 검사 초안이 ①`display:none` 요소의 rect=0, ②전폭 컨테이너의 보더박스(텍스트가 아님)로 38개 오탐 — RED 단계에서 발견해 교정했다.
18. **시각 E2E는 기본 화면만 찍지 않는다** — URL별 390·1440 기본 화면에 더해 결과가 바뀐 입력, 오류/검토, 모달/차단 상태를 찍는다. 하니스는 파일 개수·가로세로·0바이트·해시 중복을 단언하고, 에이전트는 파일을 실제로 열어 시장 적합성·위계·크롭·반복을 판정한다. 스크린샷을 저장했다는 사실만으로 PASS하지 않는다.
19. **absolute/fixed 자식은 containing block을 잰다** — 모바일 미디어쿼리에서 부모의 `position`을 바꿨다면 각 절대 배치 자식의 `offsetParent` 또는 기준 rect가 의도한 컨테이너인지 단언한다. `overflow-x:hidden`으로 누수를 숨기지 않는다.
20. **정적 검사는 재귀 입력과 대상 수를 잠근다** — 서브페이지가 생기는 저장소에서 한 단계 glob은 금지한다. 실행 전에 발견한 HTML/CSS/JS 파일 수를 출력하고 0개 또는 이전 계약보다 적으면 실패시킨다.
21. **시나리오·단언·캡처 수를 hard-lock한다** — 대규모 E2E는 `EXPECTED_SCENARIOS`, `EXPECTED_ASSERTIONS`, `EXPECTED_CAPTURES`를 둔다. 리팩터링으로 검사가 삭제돼도 전체가 조용히 GREEN이 되지 않게 한다. 수를 채우기 위한 중복 단언은 금지하고 공통·정상·오류·부작용·접근성·시각 상태로 분류한다.
22. **사용자 승인과 검증 결과는 다른 상태다** — 사용자가 방향 게이트를 자율 승인했어도 기계·기능·시각 게이트는 면제되지 않는다. 승인됨/검증됨을 보고서에서 별도 표기한다.
23. **혼합 액션 행은 직접 자식 hitbox 중심을 비교한다** — 같은 액션 묶음·같은 행의 직접 자식인 채운 버튼과 텍스트 링크가 둘 다 44px 이상인지, `rect.top + rect.height / 2` 차이가 브라우저 CSS 픽셀 2px 이하인지 단언한다. 중첩 아이콘·배지나 모바일 세로 스택은 비교 대상이 아니다. `align-items:center` 선언 존재는 검사가 아니다.
24. **연속 섹션 토폴로지를 목록화한다** — 섹션별 `역할 / DOM 골격 / 회색조 실루엣`을 적는다. 역할이 다른 연속 3개가 같은 `제목+목록` 골격이면 시각 RED다. 반복 데이터처럼 같은 골격이 맞는 경우는 이유를 기록한다.
25. **조건부 패널의 닫힘은 트랙 회수까지 단언한다** — 데스크톱 분할 작업대는 `display:none`만 검사하지 않는다. 인스펙터가 닫히면 주 표면의 오른쪽 끝과 작업대 끝 차이가 CSS 픽셀 2px 이하인지, 다시 선택하면 분할 트랙이 복원되는지 잰다. 모바일 시트·전체 화면 패널은 트랙 대신 닫힘·배경 복귀·포커스 복원을 검증한다.
26. **진실 라벨은 개수가 아니라 의미 범위를 단언한다** — 같은 상태·출처·행동 가능성을 공유하는 자식은 제목과 경계가 분명한 가장 가까운 공통 부모가 한 번 소유하고 프로그램적으로 연결한다. 상태가 다른 자식만 예외 라벨을 둔다. 같은 공개 문구가 한 그룹의 모든 자식에 복제되면 범위 설계를 다시 본다.
27. **보이는 입력과 판정 의존성을 같은 SSOT로 잠근다** — 폼의 사용자 조건 이름 집합과 순수 판정 함수가 참조하는 사용자 조건 집합을 비교한다. 숨은 기본값을 사용자 선호로 세지 않고, 보이는 입력을 무시하지 않으며, 분석 전 완료 결과가 없고 복합 비용 일부로 적합을 확정하지 않는지 단언한다.
28. **공개와 관리 콘텐츠 소유권을 테스트한다** — 공개 DOM에는 내부 ID·원문 출처 원장·규제 채널 상수·감사 로그를 복제하지 않는다. 대신 사용자 행동을 막거나 바꾸는 제한과 해석 가능한 이유는 남긴다. 관리자는 그 요약을 재현하는 출처·검증 이벤트·판정 기록을 가진다.
## 리포트 양식