typefacelisted
Install: claude install-skill snwlee/Nereus
# typeface
nereus:common 규칙을 따른다. 담당 에이전트: l10n-engineer.
## 0. 진짜 제약은 번역이 아니라 폰트다
도너(19 로케일 실운영, 읽기 전용)에서 나온 실측이다:
- **Oswald/Rubik/Didot 은 한국어·일본어·태국어를 빈 네모로 그린다.**
- **렌더러는 빠진 글리프를 `.notdef` 로 그리고 `exit 0` 한다.**
로케일 하나가 통째로 두부로 나가는데 **모든 게이트가 초록이다.**
- RTL 에서 두 톤 타이틀이 문자열을 쪼개면 셰이퍼가 공백을 잃고 순서를 뒤집는다.
- **아랍 우선 폰트에는 라틴 숫자가 없다** — "4K" 가 아랍어 옆에서 두부가 됐다.
라틴·아랍을 같이 덮는 얼굴이 필요하다.
- CJK 는 "Bold" 요청이 **SemiBold 에 이름 매칭**되어 한국어만 얇게 나왔다.
19 에서 이미 이랬다. **86 이면 스크립트 커버리지가 지배적 제약이다** —
RTL 만 7종(`ar`·`ur`·`iw-IL`·`fa` 4변종)이고 인도계·동남아 스크립트가 크게 는다.
**폰트를 찾기 전에 폰트 트리 전체를 `find` 한다.** 도너가 "없다"고 결론낸 얼굴들이
전부 있었고, 잘못된 경로를 본 것이었다.
## 1. 하네스는 폰트를 파싱하지 않는다 — 증거를 요구한다
이유 둘:
1. 폰트 파싱은 새 런타임 의존성을 부른다.
2. **하네스가 파싱해도 그 사고를 못 막는다.** 실제 렌더러가 고른 얼굴과 다를 수 있고,
사고는 "폰트에 글리프가 없다"가 아니라 **"렌더러가 두부를 그리고 성공했다"** 였다.
검증은 **렌더 직후 그 자리에서** 해야 의미가 있다.
그래서 프로젝트가 증거를 제출한다:
```json
"render": {
"ko-KR": { "glyphCheck": { "ranAt": "2026-09-13", "tool": "fonttools", "missing": [] }, "titleRuns": 1 }
}
```
| 위반 코드 | 뜻 |
|---|---|
| `tofu-unverified` | 렌더 대상인데 증거가 없다. **미설정을 통과로 읽지 않는다** |
| `glyph-missing` | 증거에 빠진 글리프가 있다. 그대로 렌더하면 두부로 발행된다 |
| `rtl-split-run` | RTL 인데 타이틀을 여러 조각으로 그린다 |
RTL 판정은 `locales.json` 의 `direction` 으로만 한다 — 코드에 목록을 박지 않는다.
`render` 를 주지 않은 로케일은 렌더 대상이 아니라 두부 검사를 하지 않는다.
## 2. 폰트 검사
```bash
echo '{"requiredEmbedding":"game","typography":{"maxFontKb":900,"minSizePx":18},"fonts":[…],"targetLocales":["ko-KR"]}' \
| node "${CLAUDE_PLUGIN_ROOT}/lib/font-check.mjs"
```
폰트 선언 형