# 06. designpaca SKILL.md 감사

작성일: 2026-08-20
대상: `D:\workspace\designpaca\packages\skill\SKILL.md` (235줄 본문) + `references/` 13개 파일
기준: `05-recommendations.md` 설계 원칙 10가지, `03-format-specs.md` 포맷 스펙
방법: 전 파일 실측(줄 수·문자 수·토큰 추정·경로 존재 여부), 어댑터 소스 4개 정독

`motion.md` 는 미작성 상태이며 지적 대상에서 제외했다. `svg-filters.md`(555줄)·`three.md`(667줄)는 감사 중 생성되어 포함했다.

---

## 0. 총평

**본문은 좋다.** 원칙 1·4·5·6·9는 사실상 그대로 구현됐고, 특히 원칙 4(조건부 규칙 + 설명 의무)와 원칙 6(design.md)는 조사한 어떤 커뮤니티 스킬보다 잘 되어 있다. 235줄 / 약 4,600토큰으로 컴팩션 생존선(5,000토큰) 안에 들어간다 — design-taste-frontend가 실패한 지점을 통과했다.

**문제는 두 곳에 몰려 있다.**
1. **문서 사이의 SSOT 붕괴** — 성능 예산 표가 3개 문서에 서로 다른 항목으로 존재하고, 가로 스크롤 기준 폭이 320px과 375px로 갈린다.
2. **어댑터의 경로 재작성 누락** — Cursor·AGENTS.md 설치본에서 본문의 `references/...` 27곳이 전부 존재하지 않는 경로를 가리킨다. 설치는 되지만 참조 문서를 못 연다.

누락된 원칙은 8(트리트먼트 보정) 하나다. 7(선언)과 10(미학/버그 분리)은 다른 형태로 이미 녹아 있다.

### 판정 요약

| 원칙 | 판정 | 근거 한 줄 |
|---|:---:|---|
| 1. references 분리 / 본문 500줄 | **준수** | 본문 235줄, 참조 13개, 인덱스 표 있음, 링크 1단계 |
| 2. 핵심 규칙 최상단 | **준수** | 28~38줄. 본문 전체가 5,000토큰 안이라 배치 리스크 자체가 없다 |
| 3. description 3부 구성 | **미흡** | 320자·3인칭·용도·트리거 ✓ / **배제 조건 없음, 한국어 리터럴 발화 없음** |
| 4. 조건부 + 오버라이드 | **준수** | 18~26줄 우선순위 체인 + "왜 이 브리프에 맞는지 한 문장" 설명 의무 |
| 5. 검증 가능한 하드 게이트 | **미흡** | 12개 중 3번이 취향 판단. 2번·11번은 정의/대안 누락 |
| 6. design.md | **미흡** | 읽기·쓰기 모두 있음 ✓ / **재실행 시 어느 단계부터인지 분기 없음** |
| 7. 코드 전 평문 선언 | **부분 준수** | 단계별 통과 조건이 그 역할을 함. 통합 선언 블록만 없음 |
| 8. 트리트먼트 보정 | **누락** | 모든 브리프가 동일한 7단계를 통과한다 |
| 9. 대담함 한 곳 | **준수** | 핵심규칙 4 + 2단계 리스크 + preflight §5 Q3 / 검증 수치만 없음 |
| 10. 미학/버그 규칙 분리 | **부분 준수** | 하드 게이트 선언문 ✓ / 성능·접근성의 협상 가능선이 문서마다 다름 |

---

## 1. 반드시 고칠 것 (우선순위 순)

### F1. 어댑터 경로 재작성 누락 — Cursor·AGENTS.md 설치본이 참조 문서를 못 연다

본문에 `references/` 로 시작하는 경로가 **27곳** 있다. Claude Code·Codex는 스킬 디렉터리를 통째로 복사하므로 상대 경로가 맞다. Cursor와 AGENTS.md는 본문만 다른 위치로 옮기고 references를 **다른 디렉터리**에 푼다.

| 타깃 | 본문이 가리키는 곳 | 실제 파일 위치 |
|---|---|---|
| Cursor | `references/galleries.md` | `.cursor/rules/designpaca/references/galleries.md` |
| AGENTS.md (project) | `references/galleries.md` | `.designpaca/references/galleries.md` |
| AGENTS.md (user) | `references/galleries.md` | `~/.designpaca/reference/references/galleries.md` |

`cursor.ts` 41~51줄과 `agents-md.ts` 40~42줄이 **문서 끝에 매핑 안내를 붙이긴 한다.** 그러나 본문 27곳의 인라인 경로는 그대로다. 에이전트는 "→ `references/galleries.md`" 를 읽고 프로젝트 루트 기준으로 열려다 실패한다. 매핑 안내는 문서 맨 아래에 있어 그때 참조되지 않는다.

**수정안** — `common.ts` 에 헬퍼 추가:

```ts
/** 본문의 `references/...` 상대 경로를 실제 설치 위치로 바꾼다.
 *  본문에서 `references/` 는 참조 파일 경로로만 쓰이므로 단순 치환이 안전하다. */
export function rewriteRefPaths(body: string, prefix: string): string {
  return body.replaceAll("references/", `${prefix}/references/`);
}
```

`cursor.ts` 54줄:
```ts
// 현재
{ kind: "write", path: mdc, content: header + ctx.skill.body + note },
// 제안
{ kind: "write", path: mdc,
  content: header + rewriteRefPaths(ctx.skill.body, ".cursor/rules/designpaca") + note },
```

`agents-md.ts` 38줄:
```ts
// 현재
ctx.skill.body,
// 제안
rewriteRefPaths(ctx.skill.body, ctx.scope === "user" ? "~/.designpaca" : ".designpaca"),
```

덤으로 `agents-md.ts` 28줄의 user 스코프 refRoot 가 `~/.designpaca/reference` 라서 최종 경로가 `~/.designpaca/reference/references/galleries.md` 로 `reference`가 두 번 들어간다. `path.join(ctx.home, ".designpaca")` 로 줄이면 project 스코프와 구조가 같아지고 위 헬퍼도 한 규칙으로 끝난다.

---

### F2. AGENTS.md 에 본문 전체(14KB)를 주입한다 — 항상 로드되는 자리에 온스킬 분량이 들어간다

`agents-md.ts` 38줄이 `ctx.skill.body` 를 통째로 넣는다. 본문은 14,088 바이트다.

AGENTS.md 는 **스킬이 아니다. 조건 없이 항상 로드된다.**

> "AGENTS.md is just standard Markdown." / "Think of AGENTS.md as a **README for agents**"
> — agents.md (03-format-specs §3.2)

그리고 Codex 는 root부터 아래로 병합하며 **기본 32 KiB 에서 자른다**. 한 블록이 14KB를 먹으면 프로젝트의 실제 AGENTS.md 내용이 잘려나갈 수 있다. 게다가 designpaca 와 무관한 모든 대화(버그 수정, 테스트 작성)에서 이 14KB를 매번 지불한다.

`03-format-specs.md` §8.4(c) 가 이 경우를 명시적으로 다뤘다: **"전체를 넣지 마라. 포인터만 넣는다."**

**수정안** — `agents-md.ts` 35~45줄의 `block` 을 포인터로 교체:

```ts
const block = [
  "## designpaca — 웹 디자인 파이프라인",
  "",
  "이 리포에서 UI를 새로 만들거나 다시 디자인할 때는 마크업·스타일을 쓰기 전에",
  `\`${refPrefix}/SKILL.md\` 를 읽고 그 파이프라인(0~6단계)을 따른다.`,
  "",
  "- 프로젝트 루트에 `design.md` 가 있으면 그것이 최상위다. 스킬 기본값을 덮는다.",
  "- 참조 문서는 각 단계에서 지시하는 것만 그때 연다. 처음부터 전부 읽지 마라.",
  "",
  `<!-- designpaca v${ctx.skill.version} — \`npx designpaca update\` 가 관리한다. 직접 고치면 업데이트가 멈춘다. -->`,
].join("\n");
```

이때 `referenceActions` 가 `SKILL.md` 도 함께 쓰도록 바꿔야 한다(현재는 references만 쓴다). `skillDirActions` 를 재사용하고 `.designpaca/` 를 루트로 주면 된다.

블록이 약 400바이트로 줄고, 본문은 필요할 때만 읽힌다.

부수: `agents-md.ts` 18줄의 `detect` 가 `.git` 존재만으로 `true` 를 낸다. 사실상 모든 리포에서 기본 선택된다. 항상 로드되는 타깃이 기본 선택되는 것은 위험하다. `AGENTS.md` 파일이 실제로 존재할 때만 `true` 로 좁히는 편이 낫다.

---

### F3. 성능 예산 표가 3개 문서에 서로 다른 항목으로 존재한다

SKILL.md 3단계는 "여기서 예산을 정하고 5단계에서 검증한다"고 한다(120·131줄). 그런데 **대조할 표가 세 개고 항목 집합이 서로 다르다.**

| 항목 | SKILL.md 122–127 | tokens.md 147–153 | preflight.md 55–61 |
|---|:---:|:---:|:---:|
| 히어로까지 JS | 150KB | 150KB (데모 400KB) | 150KB |
| WebGL 추가분 | +200KB | +200KB (데모 +600KB) | 없음 |
| 첫 인터랙션 | 3초 | 3초 (데모 5초) | 3초 |
| 폰트 파일 수 | 없음 | 2개 이하 (데모 3개) | 없음 |
| 총 전송량 | 없음 | 없음 | **1MB** |
| LCP | 없음 | 없음 | **2.5초** |
| CLS | 없음 | 없음 | **0.1** |
| 애니메이션 속성 | 합성 전용 | transform/opacity (타협 없음) | 없음 |

3단계에서 정한 예산에 총 전송량·LCP·CLS 가 없는데 5단계가 그걸 검증하라고 한다. 반대로 3단계가 정한 폰트 개수는 5단계에서 검증하지 않는다.

**수정안** — `tokens.md` §5 를 단일 원본(SSOT)으로 삼는다.

1. `tokens.md` §5 표에 `총 전송량 1MB / 2MB`, `LCP 2.5초 / 3.5초`, `CLS 0.1 / 0.1` 세 행을 추가한다. (데모 열 값은 팀 리드 판단)
2. SKILL.md 120~129줄의 표를 지우고 두 줄로 바꾼다:

```markdown
**성능 예산도 여기서 정한다. 나중에 정하면 이미 늦는다.** 표는 `references/tokens.md` §5.

기본선: 히어로까지 JS 150KB(gzip) / 첫 인터랙션 3초 / 애니메이션은 `transform`·`opacity` 만.
브리프가 데모·포트폴리오라면 예산을 올려도 된다. **올린다는 사실과 이유를 명시해라.**
```

3. `preflight.md` §2 표의 "기본 예산" 열을 지우고 `tokens.md` §5 를 참조하게 한다. 이 문서는 **실측 열만** 갖는다.

본문 8줄이 줄고, 값이 어긋날 경로가 사라진다.

---

### F4. 하드 게이트 3번은 검증 불가능하다 — 취향 판단이 섞여 있다

```
3. 코너 반경이 규칙 없이 섞여 있는가?
```

"규칙 없이"를 누가 판정하는가. 게이트 서문(173줄)이 "취향이 아니라 **버그**다. 여기엔 오버라이드가 없다"라고 선언한 목록에 주관 판단이 하나 들어가면, 모델은 그 항목을 통과 표시하고 넘어가는 법을 배운다. 그러면 나머지 11개의 권위도 같이 내려간다. (`01-local-skill-teardown.md` §4.1 — design-taste-frontend 가 "use sparingly" 표현으로 실패한 것과 같은 구조)

**수정안** — 셀 수 있는 형태로:

```
3. `border-radius` 값이 토큰 밖에 있거나, 서로 다른 값이 3종 이상인가?
```

같은 이유로 두 항목에 손이 필요하다.

**2번** — `2. 한 페이지에서 강조색이 2개 이상인가?`
`tokens.md` §2 규칙 1은 "예외: 상태색(성공/경고/오류)은 강조색이 아니라 기능색이다"라는 예외를 둔다. 게이트에는 그 예외가 없어서 상태색이 있는 폼 페이지가 오탐으로 걸린다.
→ `2. 상태색(성공·경고·오류)을 제외하고, 한 페이지에서 강조색이 2개 이상인가?`

**11번** — `11. 사용자가 주지 않은 수치가 페이지에 있는가?`
판정은 가능하지만 **대안이 없다.** 걸렸을 때 무엇을 하라는 지시가 없으면 모델은 숫자를 지우고 섹션을 망가뜨리거나, 그냥 놔둔다. `antipatterns.md` §3 "근거 없는 지표 배너" 행에 대안이 있지만 게이트에서 그리로 연결되지 않는다.
→ 항목 뒤에 한 줄 추가:

```
   걸렸으면 셋 중 하나다: (a) 숫자를 `—` 로 바꾸고 "확인 필요" 라벨을 붙인다,
   (b) 사용자에게 실제 값을 묻고 멈춘다, (c) 그 섹션 자체를 다른 구조로 바꾼다.
   숫자 모양의 구멍은 정직하고, 지어낸 숫자는 슬롭이다.
```

나머지 9개는 전부 grep 또는 계산으로 판정된다. 유지.

---

### F5. Cursor 어댑터 — Windsurf 를 감지하면서 Windsurf 가 읽지 않는 파일을 쓴다

`cursor.ts` 는 `label: "Cursor / Windsurf"`(14줄), `hint`(15줄), `detect`(22~23줄, `.windsurf`·`.windsurfrules` 확인)로 Windsurf 를 포함한다고 선언한다. 그런데 산출물은 `.cursor/rules/designpaca.mdc` 하나다.

**Windsurf 는 `.cursor/rules/*.mdc` 를 읽지 않는다.** (`03-format-specs.md` §5)

| 항목 | Cursor | Windsurf |
|---|---|---|
| 경로 | `.cursor/rules/*.mdc` | `.windsurf/rules/*.md` (또는 `.devin/rules/*.md`) |
| 프론트매터 | `description` / `globs` / `alwaysApply` | `trigger` / `globs` |
| 크기 상한 | 500줄 권고 | **12,000자 하드** |

`.windsurfrules` 가 있는 프로젝트에서 이 어댑터를 선택하면 사용자는 설치됐다고 믿지만 Windsurf 는 아무것도 못 읽는다.

**수정안 — 둘 중 하나.**

**(a) 정직하게 좁힌다 (권장, 변경 최소)**
- 14줄 `label: "Cursor"`
- 15줄 `hint: ".cursor/rules/designpaca.mdc — 프로젝트 단위"`
- 22~23줄 `.windsurf`·`.windsurfrules` 감지 제거

**(b) Windsurf 어댑터를 따로 만든다**
`.windsurf/rules/designpaca.md` 에 아래 프론트매터로 쓴다. 본문 문자 수가 **7,271자**라 12,000자 상한 안에 들어간다(측정치, 여유 4,700자).

```yaml
---
trigger: model_decision
description: <SKILL.md description 그대로>
---
```

`trigger: always_on` 을 쓰면 안 된다. 디자인 스킬이 모든 메시지의 시스템 프롬프트에 상주하게 된다.

---

## 2. 원칙별 상세 감사

### 원칙 1 — references 분리 / 본문 500줄 · 5,000토큰 · 참조 1단계

**판정: 준수.**

| 측정 항목 | 값 | 기준 | 판정 |
|---|---|---|---|
| 본문 줄 수 | 235 | ≤ 500 | ✓ |
| 본문 문자 수 | 7,271 | — | — |
| 본문 바이트 | 14,088 | — | — |
| 본문 추정 토큰 | 약 4,600 | < 5,000 | ✓ (여유 400) |
| 참조 파일 수 | 13 (motion.md 제외) | — | — |
| 참조 링크 깊이 | 1단계 | 1단계 | ✓ |
| 인덱스 표 | 219~233줄 | 있어야 함 | ✓ |

44줄의 지시가 특히 정확하다:

> 참조 문서는 **해당 단계에 들어갈 때 읽는다.** 처음부터 전부 읽지 마라 — 컨텍스트 낭비다.

`02-prompt-techniques.md` 기법 4(인덱스-후-선택)를 그대로 구현했다. 프리셋도 "고른 프리셋 파일 **하나만** 읽어라. 넷 다 읽지 마라"(107줄)로 명시했다.

**참조 깊이 확인**: `presets/README.md` → 개별 프리셋은 형식상 2단계로 보이나, SKILL.md 100~105줄이 개별 프리셋 파일을 **직접** 링크하므로 실질 1단계다. 문제없다.

**미흡 — 긴 참조 파일에 목차가 없다.**

| 파일 | 줄 수 | 목차 |
|---|---:|:---:|
| three.md | 667 | 없음 |
| svg-filters.md | 555 | 없음 |
| experimental-canvas.md | 350 | 없음 |
| antipatterns.md | 267 | 없음 |

> "For reference files longer than 100 lines, include a table of contents at the top. **This ensures Claude can see the full scope of available information even when previewing with partial reads.**"
> — Anthropic Skill authoring best practices

667줄 파일은 부분 읽기(`head -100` 등)로 훑을 가능성이 높고, 그때 뒷부분의 존재 자체를 모른다. 각 파일 상단에 3~8줄짜리 섹션 목록을 넣으면 해결된다. 우선순위는 낮다(설계 결함이 아니라 누락).

---

### 원칙 2 — 핵심 규칙 최상단

**판정: 준수.**

28~38줄 "핵심 규칙" 5개 + 접근성 예외 선언이 본문 앞 16% 지점에 있다. 그리고 18~26줄 우선순위 체인이 그보다 앞이다. 배치가 맞다.

**하드 게이트가 171줄(71% 지점)에 있는 점**은 원칙 2와 형식상 어긋나지만, 실측 결과 **문제가 되지 않는다.** 본문 전체가 약 4,600토큰이라 컴팩션 재부착 예산 5,000토큰 안에 통째로 들어간다.

> "Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each."
> — Claude Code skills docs

design-taste-frontend(22,000토큰)가 §9·§14를 잃는 실패를 designpaca 는 구조적으로 피했다. **여유는 400토큰뿐이므로, 앞으로 본문에 무엇을 추가하든 같은 분량을 다른 데서 빼야 한다.** F3(성능 예산 표 8줄 삭제)이 그 여유를 만든다.

---

### 원칙 3 — description 3부 구성

**판정: 미흡.**

측정: 320자, 3인칭, 용도 ✓, 트리거 ✓("~할 때 쓴다" + "Use when...").

| 요소 | 상태 |
|---|---|
| 무엇을 하는가 | ✓ "웹 디자인 전 과정을 끌고 가는 파이프라인 스킬" |
| 대상 | ✓ "랜딩 페이지·포트폴리오·마케팅 사이트·웹앱 UI" |
| 영문 트리거 | ✓ "Use when building or redesigning any website..." |
| **한국어 리터럴 발화** | **없음** |
| **배제 조건** | **없음** |

SKILL.md 16줄에는 "쓰지 않는다" 목록이 있지만, **본문은 스킬이 발동한 뒤에야 읽힌다.** 발동 여부를 결정하는 것은 description 뿐이다.

> `description: Explain exactly when this skill **should and should not** trigger.`
> — Codex 스킬 문서 (03-format-specs §3.1)

이 사용자는 한국어로 대화한다. `codex-image` 스킬이 한국어 발화를 나열한 이유가 그것이다(`01-local-skill-teardown.md` 패턴 D).

**수정안** — 현재 320자를 약 430자로. 스펙 상한 1,024자, Claude Code 목록 상한 1,536자 안이며, 스킬 목록 예산(컨텍스트 1%) 관점에서도 여전히 안전한 범위다.

```yaml
description: "웹 디자인 전 과정을 끌고 가는 파이프라인 스킬. 랜딩 페이지·포트폴리오·마케팅 사이트·웹앱 UI를 새로 만들거나 기존 사이트를 리디자인할 때 쓴다. \"랜딩 만들어줘\", \"디자인 예쁘게 해줘\", \"이 페이지 다시 디자인\", \"히어로 섹션 만들어줘\", \"UI 좀 살려줘\", \"design a landing page\", \"make this look better\", \"redesign this page\" 같은 요청에 발동한다. 레퍼런스 조사 → 방향 결정 → 디자인 토큰 → 구현 → 셀프 감사까지 순서대로 진행하고, AI가 만든 티 나는 결과물을 구체적 지문 목록으로 차단한다. 대시보드의 데이터 밀도 설계·차트·순수 백엔드, 그리고 버그 수정이나 기능 추가처럼 시각 결과가 목적이 아닌 작업에는 쓰지 않는다."
```

바뀐 것: 한국어 발화 5개 추가, 영문 발화 3개로 확장, 배제 조건 한 문장 추가, 중복되던 "(SVG 필터·three.js·인터랙티브 모션)" 축약.

---

### 원칙 4 — 조건부 규칙 + 오버라이드

**판정: 준수. 이 스킬에서 가장 잘 된 부분이다.**

18~26줄:

> ```
> 사용자의 명시적 지시  >  프로젝트의 design.md  >  프로젝트의 기존 토큰·코드  >  designpaca 기본값
> ```
> 사용자가 "보라색으로 해달라"고 하면 보라색으로 한다. 아래 규칙은 **브리프가 침묵할 때의 기본값**이지 금지 목록이 아니다. 단 기본값을 벗어날 때는 **왜 이 브리프에 그것이 맞는지 한 문장으로 말하고** 진행한다. 말할 수 없으면 그건 결정이 아니라 기본값 회귀다.

`05-recommendations.md` 원칙 4가 요구한 세 요소(우선순위 체인 / 오버라이드 경로 / 설명 의무)가 전부 있다. 마지막 문장은 design-taste-frontend §4.1의 "AND you can articulate why"보다 짧고 더 명확하다.

**작은 어긋남 하나.** 26줄이 "아래 규칙은 ... 금지 목록이 아니다"라고 선언한 뒤, 171~186줄이 "여기엔 오버라이드가 없다"고 한다. 문서 안에 두 등급이 있는데 26줄이 그 사실을 예고하지 않는다.

**수정안** — 26줄 끝에 한 문장 추가:

```markdown
예외는 두 곳이다. 38줄의 접근성과 5단계의 하드 게이트 12개는 브리프가 요청해도 오버라이드하지 않는다. 그 둘은 취향이 아니라 결함이기 때문이다.
```

---

### 원칙 5 — 검증 가능한 하드 게이트

**판정: 미흡.** (수정안은 F4)

게이트 12 + 카운트 규칙 5 = 17개. `05-recommendations.md` 가 권한 20~30개 이하이며 적정하다. Hallmark 의 58개나 design-taste-frontend 의 60개처럼 "정직한 검사가 불가능한 분량"이 아니다.

서문(173줄)이 정확하다:

> 취향이 아니라 **버그**다. 여기엔 오버라이드가 없다. 체크박스가 아니라 질문이니 실제로 검사해라.

"체크박스가 아니라 질문"을 명시한 것은 좋다. `02-prompt-techniques.md` 기법 15의 핵심이다.

**항목별 검증 가능성:**

| # | 항목 | 판정 방법 | 판정 |
|:--:|---|---|:---:|
| 1 | 인라인 hex/rgb/oklch, 인라인 font-family | grep | ✓ |
| 2 | 강조색 2개 이상 | 토큰 개수 | △ 상태색 예외 누락 |
| 3 | 코너 반경이 규칙 없이 섞임 | — | **✗ 주관** |
| 4 | 테마 뒤집힘 | 섹션별 배경 명도 비교 | ✓ |
| 5 | 320~1920px 가로 스크롤 | 렌더 확인 | ✓ (단 F6 참조) |
| 6 | 버튼 라벨 2줄 접힘 | 렌더 확인 | ✓ |
| 7 | 버튼 대비 4.5:1 미만 | 계산 | ✓ |
| 8 | transform/opacity 외 애니메이션 | grep | ✓ |
| 9 | `100vh` 사용 | grep | ✓ |
| 10 | `addEventListener('scroll')` | grep | ✓ |
| 11 | 사용자가 주지 않은 수치 | 브리프 대조 | △ 대안 누락 |
| 12 | div 가짜 스크린샷 | 소스 확인 | ✓ |

**카운트 규칙 5개는 전부 검증 가능하다.** 다만 4번째 항목에 미세한 긴장이 있다:

> - 작은 대문자 라벨(eyebrow) 개수 ≤ `ceil(섹션수 / 3)`

`antipatterns.md` §0 2위 항목은 "헤드라인·섹션 라벨이 전체 대문자"를 검출률 10.5%로 지목하며 대안을 **"라벨을 없애고 헤드라인만으로 섹션을 구분"** 이라고 한다. 즉 antipatterns 는 0개를, SKILL.md 는 `ceil(n/3)`개를 허용한다. 둘 다 성립하려면 SKILL.md 쪽이 "**전체 대문자가 아닌** 작은 라벨은 `ceil(n/3)`까지"라는 뜻이어야 한다. 지금 문장으로는 읽히지 않는다.

**수정안** — 192줄:
```markdown
- 작은 라벨(eyebrow) 개수 ≤ `ceil(섹션수 / 3)`. **전체 대문자 라벨은 개수와 무관하게 0개다**(antipatterns §0)
```

---

### 원칙 6 — design.md

**판정: 미흡 (핵심은 준수, 분기 하나 누락).**

읽기(0단계 50줄)와 쓰기(6단계 202~215줄)가 모두 있다. Superdesign·Hallmark·stitch-design-taste 세 시스템이 각각 도달한 패턴을 그대로 구현했고, 213줄이 특히 좋다:

> 마지막 줄이 가장 중요하다. **하지 않기로 한 결정을 적어두지 않으면 다음 사람이 그것을 "빠뜨린 것"으로 착각하고 되돌린다.**

**누락 — 두 번째 실행에서 어느 단계부터인지가 없다.**

50줄이 말한다:

> 먼저 프로젝트 루트에 `design.md` 가 있는지 확인한다. 있으면 읽고, 그 결정을 이 스킬의 기본값보다 우선한다. 같은 프로젝트를 두 번째로 작업할 때 지난번과 다른 디자인이 나오면 그건 실패다.

그런데 파이프라인은 42줄에서 "**순서를 바꾸지 마라.** 각 단계에는 통과 조건이 있고, 통과하지 못하면 다음 단계로 가지 않는다"고 한다. `design.md` 가 있는 프로젝트에서 페이지 하나를 추가할 때, 모델은 R1/R2/R3 갤러리 조사를 다시 하고 프리셋을 다시 고르고 리스크를 다시 정해야 한다. 그러면 50줄이 경고한 "지난번과 다른 디자인"이 정확히 발생한다.

**수정안** — 0단계 50줄 뒤에 분기 추가:

```markdown
`design.md` 가 있으면 **1·2단계를 건너뛴다.** 레퍼런스와 방향은 이미 정해져 있다.
읽고 그 값을 3단계 토큰으로 그대로 가져간 뒤 4단계로 간다.
1·2단계를 다시 도는 것은 사용자가 "방향을 바꾸자"고 명시할 때뿐이며,
그때는 새 결정으로 `design.md` 를 갱신한다.
```

그리고 219줄 참조 표의 "언제 읽나" 열에도 이 분기를 반영해두면 좋다.

**낮은 우선순위 — 프로젝트 간 회전 장치가 없다.**
`design.md` 는 **한 프로젝트 안의** 일관성을 보장한다. 서로 다른 프로젝트 5개가 전부 `swiss-minimal` 을 고르는 것은 막지 못한다. 프리셋이 4개뿐이라 이 위험은 실재한다. Hallmark 가 `.hallmark/log.json` 으로 푼 문제다(`02-prompt-techniques.md` 기법 12).

다만 designpaca 는 프로젝트 단위 설치가 기본이라 전역 로그를 둘 자리가 애매하다. **지금 단계에서는 넘기고**, 대신 2단계에 한 줄을 넣어두는 정도가 비용 대비 합리적이다:

```markdown
프리셋을 고른 이유를 한 줄로 적어라. "제품이 복잡해서"처럼 브리프에서 나온 이유여야 한다.
"무난해서"는 이유가 아니다 — 그건 네 기본값이지 이 브리프의 결정이 아니다.
```

---

### 원칙 7 — 코드 전 평문 선언

**판정: 부분 준수. 추가는 선택이다.**

원칙 7이 요구한 것은 "코드를 쓰기 전에 선택을 사용자가 읽을 수 있는 형태로 낸다"이다. designpaca 는 이것을 **단계별 통과 조건**으로 분산 구현했다:

| 단계 | 선언 산출물 | 위치 |
|---|---|---|
| 0 | 브리프 3줄 | 54~58줄 |
| 1 | R1/R2/R3 + 6축 수치 + 회색조 위계 | `reference-method.md` §6 필수 블록 |
| 2 | 한 문장 컨셉 + 프리셋 + 리스크 하나 | 96~98줄 |
| 3 | 토큰 실제 값 + 성능 예산 | 131줄 |

그리고 237줄이 "**단계를 보고하며 진행해라.** 사용자는 어느 단계인지 알아야 개입할 수 있다"로 받친다. 238줄의 "가정은 소리 내서 말해라"도 같은 계열이다.

**이것으로 충분하다.** Hallmark 식 통합 프리뷰 블록은 이 구조 위에 얹으면 오히려 같은 정보를 두 번 출력하게 된다.

**다만 한 가지가 빠져 있다** — 3단계와 4단계 사이에 **되돌아볼 수 없는 지점**이 있다. 4단계에 들어가면 코드가 나오기 시작하고, 그때 사용자가 방향을 바꾸면 전부 버려야 한다. 2단계 통과 조건(109줄)이 사용자 확인을 요구하지 않는다.

**수정안(선택)** — 3단계 통과 조건(131줄) 뒤에 한 줄:

```markdown
> 통과 조건: 토큰이 실제 값으로 적혔고, 성능 예산이 숫자로 정해졌다.
> **4단계로 넘어가기 전에 0~3단계의 결정을 6줄로 요약해 보여준다.** 여기가 되돌리기 가장 싼 지점이다.
> `무엇을 / 누구에게 / R1·R2·R3 / 컨셉 / 프리셋 / 리스크` 각 한 줄.
```

6줄이면 토큰 비용이 거의 없고, 잘못된 방향으로 400줄 HTML을 만드는 것보다 훨씬 싸다.

---

### 원칙 8 — 트리트먼트 보정

**판정: 누락. 추가를 권한다.**

SKILL.md 12~16줄은 **범위**만 정의한다(쓴다 / 쓰지 않는다). 범위 안에 들어온 모든 브리프는 동일한 7단계를 통과한다.

문제는 범위 안에도 편차가 크다는 것이다.

| 브리프 | 현재 요구되는 것 | 적절한가 |
|---|---|---|
| 브랜드 랜딩 페이지 | R1/R2/R3 조사 + 리스크 하나 + design.md | 적절 |
| 사내 도구 설정 화면 | 동일 | **과잉** |
| API 문서 페이지 | 동일 | **과잉** |
| 데모용 실험 페이지 | 동일 | 적절 |

`03. 화려함은 4순위다`(34줄)와 `핵심 규칙 4. 대담함은 한 곳에만`(35줄)이 과잉 장식은 막는다. 그러나 **"감수할 리스크 하나"(98줄)는 필수**다:

> **감수할 리스크 하나** — 정당화할 수 있는 과감한 선택 하나. 없으면 그 디자인은 안전하고 잊힌다

사내 문서 페이지에 "잊히지 않기 위한 과감한 선택"을 요구하는 것은 잘못된 목표다. `artifact-design` 이 이 문제를 정확히 짚었다:

> **Calibrate treatment, not whether to design.** ... Many requests call for a more utilitarian treatment: a plan, a memo, a demo. Make it polished ... **but avoid over-designing.**
> **When unsure: a well-composed page is never the wrong answer; an over-designed visual identity sometimes is.**

**수정안** — 0단계 브리프 게이트에 축 하나 추가. 3줄 블록 바로 뒤(58줄과 60줄 사이):

```markdown
**트리트먼트를 정한다.** 같은 완성도를 어느 형태로 전달할지의 문제다.

- **에디토리얼** — 랜딩, 포트폴리오, 캠페인, 제품 소개. 사용자가 자랑할 물건.
  → 전 단계를 그대로 돈다. 리스크 하나는 필수다.
- **유틸리티** — 사내 도구, 문서 페이지, 관리 화면, 데모.
  → 1단계 레퍼런스는 R1 하나로 줄인다. 2단계 리스크는 **생략한다**.
  타입 위계·여백·토큰·접근성은 그대로 지킨다. 여기서 완성도가 결정된다.
  거대한 히어로도 스크롤 연출도 필요 없다.

확신이 서지 않으면 유틸리티로 간다.
**잘 구성된 페이지가 틀린 답이 된 적은 없다. 과잉 디자인된 아이덴티티는 가끔 틀린 답이다.**
```

그리고 2단계 98줄의 리스크 항목을 조건부로:

```markdown
- **감수할 리스크 하나** — 정당화할 수 있는 과감한 선택 하나. 없으면 그 디자인은 안전하고 잊힌다.
  **(유틸리티 트리트먼트면 생략한다. 거기서는 안전한 것이 맞다.)**
```

추가 분량 약 11줄. F3에서 8줄을 빼므로 순증 3줄, 토큰 여유 안에 들어간다.

---

### 원칙 9 — 대담함은 한 곳에만

**판정: 준수. 검증 수치만 없다.**

세 지점에 일관되게 박혀 있다:

- 핵심 규칙 4 (35줄): "**대담함은 한 곳에만.** 리스크는 하나다. 나머지는 조용히 받쳐준다. 두 곳에서 소리치면 둘 다 죽는다."
- 2단계 (98줄): "감수할 리스크 하나"
- `preflight.md` §5 Q3: "감수하기로 한 리스크가 실제로 들어갔는가? → 구현 중에 안전한 쪽으로 후퇴하지 않았는지"

Q3이 특히 좋다. 원칙 9의 "위험을 안 지는 것도 위험이다"를 검사 항목으로 바꿨다.

**미흡 — 검증 가능한 수치가 없다.**
`05-recommendations.md` 원칙 9가 권한 "액센트 면적 상한"이 어디에도 없다. `tokens.md` §2 규칙 2("채도가 높은 색은 면적을 좁게")는 정성적이고, `reference-method.md` 축3의 "accent 면적 %(10% 이하가 정상)"는 **레퍼런스를 분석할 때** 쓰는 값이지 자기 결과물 검사용이 아니다.

**수정안** — 카운트 규칙(188~196줄)에 한 줄 추가:

```markdown
- 강조색이 차지하는 화면 면적 ≤ 뷰포트의 10% (`reference-method.md` 축3과 같은 기준)
```

Hallmark 는 이 값을 5%로 잡는다. 10%는 `reference-method.md` 와 일치하므로 문서 간 정합성 면에서 10%가 낫다.

---

### 원칙 10 — 미학 규칙과 버그 규칙 분리

**판정: 부분 준수.**

분리 개념은 두 곳에 있다:

- 38줄: "**접근성은 예외다. 이것만은 협상하지 않는다.** 키보드·포커스·대비·`prefers-reduced-motion`은 어떤 이펙트보다, 어떤 브리프보다 우선한다. **픽셀은 왜곡해도 DOM은 살린다.**"
- 173줄: "취향이 아니라 **버그**다. 여기엔 오버라이드가 없다."

마지막 문장("픽셀은 왜곡해도 DOM은 살린다")은 HTML-in-Canvas 같은 실험 경로까지 커버하는 좋은 문장이다.

**미흡 3가지.**

**(a) 접근성 선언과 하드 게이트가 어긋난다.**
38줄이 협상 불가로 지목한 넷은 `키보드 · 포커스 · 대비 · prefers-reduced-motion` 이다. 하드 게이트 12개 중 접근성 항목은 7번(버튼 대비)뿐이다. 키보드·포커스·reduced-motion 은 게이트에 없다.

`preflight.md` §1 표가 그 셋을 모두 다루고, 5단계 통과 조건(198줄)이 `preflight.md` 통과를 요구하므로 **기능적으로는 커버된다.** 그러나 "협상하지 않는다"고 선언한 넷 중 하나만 게이트에 있는 것은 읽는 사람에게 불일치로 보인다.

→ 수정안: 게이트를 늘리지 말고(분량), 173줄 서문에 한 줄:
```markdown
접근성 전체는 `preflight.md` §1에서 검사한다. 아래는 그 외에 자주 깨지는 것들이다.
```

**(b) 성능의 협상 가능선이 문서마다 다르다.**
- SKILL.md 핵심 규칙 5(36줄): "데모·포트폴리오 브리프면 예산을 올려도 되지만 **올렸다고 말해야 한다**" → 조건부
- `tokens.md` §5 표: `애니메이션 속성 | transform/opacity 만 | 동일 (타협 없음)` → 성능 안에서도 이 항목만 절대
- 하드 게이트 8번: `transform`/`opacity` 외 애니메이션 → 절대

즉 성능은 "예산은 조건부, 애니메이션 속성은 절대"라는 이중 구조인데, SKILL.md 36줄만 읽으면 전부 조건부로 읽힌다.

→ 수정안: 36줄 끝에 한 문장:
```markdown
단 애니메이션 속성만은 예외다. `transform`·`opacity` 제한은 예산과 무관하게 지킨다 — 그건 예산 문제가 아니라 렌더링 파이프라인 문제다.
```

**(c) 하드 게이트에 실무 렌더링 버그 몇 개가 빠졌다.**
`05-recommendations.md` 원칙 10이 여러 소스에서 반복 확인된 것으로 정리한 항목 중 다음이 어디에도 없다:

| 항목 | 근거 | 현재 상태 |
|---|---|---|
| `width: 100vw` 금지 (스크롤바 있는 데스크톱에서 깨짐) | Hallmark anti-patterns | 없음 |
| 이미지가 들어가는 그리드 트랙에 `minmax(0, 1fr)` | Hallmark gate 50 | 없음 |
| 디스플레이 텍스트에 `overflow-wrap: anywhere` | Hallmark gate 51 | `preflight.md` §3에 있음 ✓ |
| 페이지 레벨 sticky 아래 또 다른 `top: 0` sticky 금지 | Hallmark gate 56 | 없음 |
| LCP 요소에 `loading="lazy"` 금지 | Hallmark anti-patterns | `preflight.md` §2에 반대 방향으로만 있음(첫 화면 밖 lazy 누락) |

이 중 앞의 셋은 **하드 게이트가 아니라 `layout.md` §4(반응형)에 넣는 것이 맞다.** 게이트를 15개로 늘리는 것보다 낫다. LCP lazy 는 `preflight.md` §2 "자주 걸리는 것"에 한 줄 추가하면 된다.

---

## 3. 중복과 모순

### 3.1 모순 — 값이 실제로 다르다

| # | 항목 | 위치 A | 위치 B | 조치 |
|:--:|---|---|---|---|
| M1 | 가로 스크롤 검사 폭 | SKILL.md 179줄 `320~1920px 사이 어느 폭에서든` | `preflight.md` 76줄 `375px 폭에서`<br>`layout.md` 109줄 `모바일 폭(375px)에서` | **320~1920px 로 통일.** 320px 은 실제로 존재하는 최소 폭(iPhone SE 세로)이고 375px 만 검사하면 그 아래가 뚫린다 |
| M2 | 성능 예산 항목 집합 | SKILL.md 122~127 (4항목) | `tokens.md` 147~153 (5항목)<br>`preflight.md` 55~61 (5항목, 서로 다름) | **F3** 참조. `tokens.md` §5 를 SSOT 로 |
| M3 | eyebrow 허용 개수 | SKILL.md 192줄 `≤ ceil(섹션수/3)` | `antipatterns.md` §0 2위 `라벨을 없애고 헤드라인만으로` (사실상 0) | **원칙 5 수정안** 참조. "전체 대문자는 0개" 를 명시해 두 규칙을 분리 |

M1 이 실질적으로 가장 위험하다. 하드 게이트 5번은 "오버라이드 없음"인데 참조 문서 두 곳이 더 느슨한 기준을 준다. 모델은 느슨한 쪽을 근거로 통과 표시할 수 있다.

### 3.2 중복 — 값은 같으나 두 번 이상 나온다

| # | 내용 | 위치 | 판단 |
|:--:|---|---|---|
| D1 | 기계 검사 3종(grep / 카피 치환 / 이펙트 끄기) | SKILL.md 165~169 · `preflight.md` §0 A·B·C | **유지.** SKILL.md 쪽이 "반드시 돌려라"라는 강조 역할을 하고 5줄뿐이다 |
| D2 | 프리셋 4종 표 | SKILL.md 100~105 · `presets/README.md` 8~13 | **유지.** 표가 SKILL.md 에 있으면 README 를 안 열어도 되어 오히려 토큰 절약. 현재 두 표는 정확히 일치한다 |
| D3 | 성능 예산 표 | 3곳 | **F3 로 정리** |
| D4 | 터치 타깃 44×44px | `preflight.md` §3 · `layout.md` §4 | 유지. 서로 다른 단계에서 필요 |
| D5 | 강조색 1개 규칙 | SKILL.md 게이트 2 · `tokens.md` §2 규칙1 · `preflight.md` §5 Q5 · `antipatterns.md` | 유지. 다만 상태색 예외는 `tokens.md` 에만 있다 → F4 |
| D6 | 한글 조판 규칙 | `antipatterns.md` §8 (전체) · `layout.md` §3 (요약 + 포인터) | **좋은 형태.** `layout.md` 가 요약하고 원본을 가리킨다 |
| D7 | 참조 문서 지도 | SKILL.md 219~233 · 각 단계 인라인 링크 | 유지. 원칙 1의 인덱스 요건 |

D6 은 다른 문서들이 따라야 할 모범이다. 요약 5줄 + "자세한 건 여기"가 전문 복사보다 낫다.

### 3.3 모순 아님 (확인함)

- **다크 모드**: `tokens.md` §2 "다크를 기본값으로 삼지 마라" vs `presets/dark-instrument.md`. 프리셋이 6~13줄에서 "다크 기본값은 단일 슬롭 시그니처 1위다. 이유를 댈 수 없으면 라이트로 가라"고 먼저 못 박고 정당화 사유 3개를 제시한다. **정확히 원칙 4의 오버라이드 구조다.** 손댈 필요 없다.
- **벤토 그리드**: `layout.md` §1 "새 기본값이라 차별화가 아니다" vs `antipatterns.md` §3 "기본 선택지로 쓰지 마라". 같은 말이고 `layout.md` 가 조건부 사용법까지 준다.

---

## 4. 분량 판정

**결론: 자르지 않아도 된다. 다만 F3(성능 예산 표 8줄)은 분량이 아니라 SSOT 때문에 빼야 한다.**

| 지표 | 값 | 기준 | 여유 |
|---|---|---|---|
| 본문 줄 수 | 235 | ≤ 500 | 265줄 |
| 본문 추정 토큰 | 약 4,600 | < 5,000 | **약 400토큰** |

토큰 여유가 400뿐이라는 점이 실제 제약이다. 이 감사에서 제안한 추가분은:

| 제안 | 증감 |
|---|---|
| F3 성능 예산 표 삭제 | **-8줄** |
| 원칙 8 트리트먼트 블록 | +11줄 |
| 원칙 4 등급 예고 1문장 | +1줄 |
| 원칙 6 design.md 분기 | +4줄 |
| 원칙 7 3단계 요약 지시 | +2줄 |
| 원칙 9 액센트 면적 카운트 | +1줄 |
| 원칙 10 (a)(b) 각 1문장 | +2줄 |
| F4 게이트 2·3·11 수정 | +3줄 |
| 원칙 5 eyebrow 문구 | +0줄 (치환) |
| **합계** | **+16줄 / 약 +300토큰** |

4,900토큰이 되어 5,000 선에 붙는다. **한 곳을 더 빼는 것을 권한다.**

가장 뺄 만한 곳은 **219~233줄 참조 문서 지도 표(15줄)** 다. 각 단계가 이미 인라인으로 파일을 지목하고 있어 정보가 중복된다. 다만 원칙 1의 인덱스 요건이라 완전 삭제는 곤란하다.

→ 절충: 표를 유지하되 "언제 읽나" 열을 단계 번호만으로 축약(`1단계 — 어느 갤러리를 볼지 정할 때` → `1`). 약 5줄 절약.

또는 **151~152줄 실험 경로 2줄**을 4-3 안으로 흡수. 미세하다.

---

## 5. 작업 2 — 포맷 어댑터 검증

### 5.1 요약

| 파일 | 판정 | 핵심 |
|---|:---:|---|
| `claude-code.ts` | **정확** | 경로·스코프 전부 스펙과 일치 |
| `codex.ts` | **경로 재검토 필요** | `~/.codex/skills` 는 실측으로 존재하나 공식 문서엔 없다 |
| `cursor.ts` | **수정 필요** | 경로 재작성 누락 · Windsurf 오표기 · YAML 인용 · 네이티브 스킬 경로 미사용 |
| `agents-md.ts` | **수정 필요** | 본문 전체 주입 · 경로 재작성 누락 |

### 5.2 `claude-code.ts` — 문제없음

`~/.claude/skills/designpaca/` (user) / `.claude/skills/designpaca/` (project). `03-format-specs.md` §2.1 표와 정확히 일치한다. `SKILL.md` 를 그대로 쓰므로 프론트매터 변환 리스크도 없다.

한 가지만 알아둘 것: Claude Code 는 심링크를 따라가고 같은 타깃이 두 경로에서 보이면 **한 번만 로드한다.**

> "if the same target is reachable from more than one location, Claude Code loads the skill once"

그러나 지금 어댑터는 각 타깃에 **실제 파일을 복사**한다. 사용자가 Claude Code 와 Codex 를 둘 다 선택하면 같은 내용의 별도 디렉터리가 두 개 생긴다. 동작에는 문제가 없다(각 도구가 자기 경로만 본다). 유지보수 관점에서 `update` 가 둘 다 갱신하는지만 확인하면 된다.

### 5.3 `codex.ts` — `~/.codex/skills` 는 실측으로 맞지만 문서 근거가 없다

**실측 결과 (이 머신):**

```
C:\Users\encep\.codex\skills\
├── .system\
│   ├── .codex-system-skills.marker   ← Codex 가 만든 파일
│   ├── imagegen\  openai-docs\  plugin-creator\
│   ├── review-agent\  skill-creator\  skill-installer\
├── frontend-design\        (2026-06-28)
├── web-design-guidelines\  (2026-06-28)
├── object-separation\      (2026-07-15)
├── viven-wiki\             (2026-04-14)
└── codex-primary-runtime\  (2026-04-24)
```

`.system/.codex-system-skills.marker` 와 그 아래 번들 스킬 6개는 **Codex CLI 자신이 만든 것**이다. 사용자가 4월부터 이 디렉터리에 스킬을 넣어 쓰고 있다. 즉 `~/.codex/skills/` 가 Codex 의 스킬 루트인 것은 거의 확실하다.

**그러나 공식 문서는 이 경로를 언급하지 않는다.** 재확인차 다시 fetch 했고 결과는 동일했다:

> Codex scans: `$CWD/.agents/skills` → `$CWD/../.agents/skills` → `$REPO_ROOT/.agents/skills` → `$HOME/.agents/skills` → `/etc/codex/skills` → 번들.
> **The documentation does not mention `~/.codex/skills` or `.codex/skills` as scan locations.**
> — learn.chatgpt.com/docs/build-skills (2026-08-20 재확인)

`~/.codex/config.toml` 에도 스킬 경로 설정은 없다(색상 항목만 검색됨).

**권고 — 두 가지 중 하나.**

**(a) `~/.agents/skills/designpaca/` 를 새 타깃으로 추가한다 (권장).**
이 경로 하나가 **Codex · Cursor · VS Code Copilot 셋 다** 문서상 스캔 대상이다.

| 도구 | `~/.agents/skills` 스캔 | 근거 |
|---|:---:|---|
| Codex | O | learn.chatgpt.com/docs/build-skills |
| Cursor | O | cursor.com/docs/context/skills |
| VS Code Copilot | O | code.visualstudio.com/docs/copilot/customization/agent-skills |

이 사용자 머신의 `C:\Users\encep\.agents\skills\` 에 design-taste-frontend 등 16개가 이미 있고, `~/.claude/skills/` 가 그리로 심링크되어 있다. **사용자가 이미 이 배치를 쓰고 있다.** 어댑터가 그 관행을 따르는 것이 자연스럽다.

**(b) `codex.ts` 를 유지하되 두 곳에 쓴다.**
`~/.codex/skills/designpaca/` (실측) + `~/.agents/skills/designpaca/` (문서). 파일이 중복되지만 확실하다.

**프로젝트 스코프는 별개 문제다.** `codex.ts` 25줄이 `.codex/skills/designpaca` 를 쓰는데, 문서가 말하는 리포 스코프는 `.agents/skills` 다. `.codex/skills` 는 실측 근거도 문서 근거도 없다.

```ts
// codex.ts 25줄 — 현재
const root = scopeRoot(ctx, [".codex", "skills", "designpaca"], [".codex", "skills", "designpaca"]);
// 제안 (project 만 교체)
const root = scopeRoot(ctx, [".codex", "skills", "designpaca"], [".agents", "skills", "designpaca"]);
```

### 5.4 `cursor.ts` — 네 가지

**① 경로 재작성 누락 → F1.** 가장 중요하다.

**② `description` 이 인용부호 없이 쓰인다.**

```ts
// 34줄
`description: ${ctx.skill.description}`,
```

`skill-source.ts` 16~18줄이 원본의 따옴표를 벗겨서 넘긴다. 현재 값은 320자에 `: ` 도 `#` 도 없어 **지금은 유효한 YAML 이다**(실측 확인). 그러나 description 에 콜론+공백이 한 번이라도 들어가면 그 순간 `.mdc` 프론트매터가 깨지고, Cursor 는 조용히 규칙을 무시한다. 원칙 3 수정안대로 문장을 늘리면 위험이 커진다.

```ts
// 제안
`description: ${JSON.stringify(ctx.skill.description)}`,
```

JSON 문자열은 YAML 의 유효한 double-quoted scalar 이므로 그대로 쓸 수 있다.

**③ `globs:` 빈 값 — 문제없다.**

```ts
"globs:",
"alwaysApply: false",
```

Cursor 문서의 4가지 규칙 타입 중 우리가 원하는 것은 "Apply Intelligently"(`description` 있음, `globs` 없음)다. 빈 `globs:` 는 YAML null 이므로 이 조건을 만족한다. Cursor UI 자신이 이 형태를 생성한다.

`alwaysApply: false` 도 정확하다. Cursor 문서가 `alwaysApply: true` 를 "Use sparingly, this is your global config"라고 경고한다. 디자인 스킬이 모든 세션에 상주해서는 안 된다.

**굳이 더 정확히 하려면** 키 자체를 빼는 쪽이 문서 표현("no `globs`")에 더 가깝다. 낮은 우선순위.

**④ Windsurf → F5.**

**⑤ 추가 권고 — Cursor 는 이제 Agent Skills 를 네이티브 지원한다.**

`.mdc` 변환은 레거시 경로다. Cursor 는 다음 넷을 스캔한다: `.agents/skills/`, `.cursor/skills/`, `~/.agents/skills/`, `~/.cursor/skills/`.

즉 **`.cursor/skills/designpaca/` 에 SKILL.md 를 그대로 쓰면 변환이 필요 없고, 경로 재작성 문제(F1)도 사라지고, references 도 그대로 옮겨간다.** 5.3(a)의 `~/.agents/skills/` 타깃을 추가하면 Cursor user 스코프까지 한 번에 덮인다.

**권고 배치:**
```
1순위  ~/.agents/skills/designpaca/   → Codex + Cursor + Copilot (user)
       .agents/skills/designpaca/     → 같은 셋 (project)
2순위  .cursor/rules/designpaca.mdc   → .mdc 를 쓰는 기존 워크플로 호환용 (레거시)
```

`cursor.ts` 16줄의 `scopes: ["project"]` 도 재검토 대상이다. 주석은 "Cursor 의 전역 규칙은 파일이 아니라 앱 설정(User Rules)이라 프로젝트 범위만 지원한다"고 하는데, **스킬은 `~/.cursor/skills/` 로 파일 설치가 된다.** 주석은 `.mdc` 규칙에 대해서는 맞고 스킬에 대해서는 틀리다.

**⑥ references 를 `.cursor/rules/` 안에 두는 것.**
`cursor.ts` 30줄이 `.cursor/rules/designpaca/` 에 참조 문서를 푼다. Cursor 는 `.cursor/rules/` 를 재귀 스캔하고, 프로젝트 규칙은 `.mdc` 확장자여야 하므로 우리 `.md` 파일들은 규칙으로 잡히지 않는다. **지금은 안전하다.** 다만 규칙 전용 디렉터리에 규칙이 아닌 파일 13개를 넣는 것은 깨지기 쉬운 가정이다. `.designpaca/` 로 빼면 AGENTS.md 타깃과 경로 규칙도 통일된다.

### 5.5 `agents-md.ts` — 세 가지

**① 본문 전체 주입 → F2.** 가장 중요하다.

**② 경로 재작성 누락 → F1.**

**③ user 스코프 경로.**
24줄이 `~/.codex/AGENTS.md` 를 쓴다. 어댑터 라벨은 "범용 AGENTS.md" 인데 이 경로는 Codex 전용이다. 이 머신에는 해당 파일이 이미 있고(436바이트) 마커 주입은 기존 내용을 보존하므로 **동작은 문제없다.**

다만 범용이라는 이름값을 하려면 user 스코프에서는 AGENTS.md 대신 `~/.agents/skills/designpaca/` 로 가는 것이 맞다. 5.3(a) 타깃이 생기면 `agents-md` 는 `scopes: ["project"]` 로 좁히는 것이 깔끔하다.

**④ `detect` 가 너무 넓다.**
```ts
// 18줄
return await exists(path.join(ctx.cwd, "AGENTS.md")) || await exists(path.join(ctx.cwd, ".git"));
```
`.git` 이 있으면 참이므로 사실상 모든 리포에서 기본 선택 후보가 된다. AGENTS.md 는 **조건 없이 항상 로드되는** 유일한 타깃이다. 기본 선택이 되기에는 비용이 크다. `AGENTS.md` 파일이 실제로 존재할 때만 `true` 로 좁히기를 권한다(없어도 사용자가 수동 선택하면 만들어진다 — 17줄 주석의 의도는 유지된다).

**⑤ 마커 처리는 잘 되어 있다.**
`marker.ts` 의 `upsertBlock`/`removeBlock`/`extractBlock` 이 블록 밖 내용을 보존한다. AGENTS.md 는 사용자 소유 문서이므로 이 설계가 맞다. `agents-md.ts` 44줄의 안내 주석("직접 고치면 업데이트가 멈춘다")도 적절하다.

한 가지: `upsertBlock` 은 블록이 없으면 **문서 끝에 덧붙인다**(marker.ts 28~29줄). AGENTS.md 는 가까운 파일이 이기고 root 부터 아래로 병합되므로 위치 자체는 무해하다. 다만 32 KiB 상한을 고려하면 F2 로 블록이 작아지는 것이 더 중요하다.

### 5.6 `common.ts` / `skill-source.ts` — 문제없음

- `.designpaca_version` 을 스킬 디렉터리에 쓰는 것: Agent Skills 스펙이 추가 파일을 허용하므로 무해하다. Cursor 의 재귀 스캔도 `SKILL.md` 만 찾으므로 영향 없다.
- `splitFrontmatter` 가 얕은 파서인 것: 현재 프론트매터가 `name` + `description` 2줄이라 충분하다. 단 **YAML 블록 스칼라(`>-`, `|`)를 지원하지 않는다.** 원칙 3 수정안대로 description 을 여러 줄로 쓰고 싶다면 파서를 먼저 손봐야 한다. 지금은 한 줄 double-quoted 를 유지하는 것이 안전하다.
- `walk()` 가 `.orig` 와 `.designpaca_version` 만 제외한다: `motion.md` 처럼 아직 없는 파일은 자연히 빠지고, 나중에 추가하면 자동으로 따라간다. 정상.

**추가 권고 — 빌드 타임 검증.**
SKILL.md 본문이 가리키는 `references/*.md` 15개 중 실제 존재는 14개다(측정 시점 기준). CLI 가 패키징 전에 다음을 확인하면 깨진 링크가 배포되는 것을 막는다:

```
본문에서 /references\/[\w\/-]+\.md/ 를 전부 뽑아 파일 존재를 확인.
없으면 빌드 실패.
```

`03-format-specs.md` §8.6 검증 체크리스트를 그대로 스크립트화하면 된다.

---

## 6. 조치 목록 (팀 리드용)

### 반드시 (5개)

| # | 파일 | 위치 | 내용 |
|:--:|---|---|---|
| F1 | `core/src/targets/common.ts`<br>`cursor.ts` 54줄<br>`agents-md.ts` 38줄 | — | `rewriteRefPaths()` 추가 후 Cursor·AGENTS.md 본문의 `references/` 27곳을 실제 설치 경로로 치환 |
| F2 | `core/src/targets/agents-md.ts` | 35~45줄 | 본문 14KB 전체 주입 → 포인터 블록(약 400B)으로 교체. `detect` 를 `AGENTS.md` 존재로 좁힘 |
| F3 | `skill/SKILL.md` 120~129<br>`references/tokens.md` §5<br>`references/preflight.md` §2 | — | 성능 예산 표를 `tokens.md` §5 단일 원본으로. SKILL.md 는 2줄 요약, preflight 는 실측 열만 |
| F4 | `skill/SKILL.md` | 176·177·185줄 | 게이트 2번에 상태색 예외, 3번을 `border-radius 3종 이상`으로 교체, 11번에 대안 3가지 추가 |
| F5 | `core/src/targets/cursor.ts` | 14·15·22~23줄 | Windsurf 표기 제거(또는 별도 어댑터). Windsurf 는 `.cursor/rules/*.mdc` 를 읽지 않는다 |

### 권장 (10개)

| # | 대상 | 내용 |
|:--:|---|---|
| R1 | `SKILL.md` 0단계 | 트리트먼트 축(에디토리얼 / 유틸리티) 추가 — 원칙 8 |
| R2 | `SKILL.md` 0단계 50줄 | `design.md` 가 있으면 1·2단계 건너뛰기 분기 — 원칙 6 |
| R3 | `SKILL.md` 프론트매터 | description 에 한국어 리터럴 발화 + 배제 조건 추가 — 원칙 3 |
| R4 | 새 어댑터 | `~/.agents/skills/designpaca/` 타깃 추가 — 한 번 써서 Codex·Cursor·Copilot 커버 |
| R5 | `codex.ts` 25줄 | project 스코프를 `.codex/skills` → `.agents/skills` 로 |
| R6 | `cursor.ts` 34줄 | `description: ${JSON.stringify(...)}` 로 YAML 인용 |
| R7 | `SKILL.md` 179줄 / `preflight.md` 76 / `layout.md` 109 | 가로 스크롤 검사 폭을 320~1920px 으로 통일 — M1 |
| R8 | `SKILL.md` 192줄 | eyebrow 규칙에 "전체 대문자는 0개" 명시 — M3 |
| R9 | `SKILL.md` 카운트 규칙 | 강조색 면적 ≤ 뷰포트 10% 추가 — 원칙 9 |
| R10 | `three.md` · `svg-filters.md` · `experimental-canvas.md` · `antipatterns.md` | 파일 상단에 3~8줄 섹션 목차 |

### 낮은 우선순위 (5개)

| # | 대상 | 내용 |
|:--:|---|---|
| L1 | `SKILL.md` 26줄 | "예외는 두 곳(접근성·하드 게이트)" 1문장 — 원칙 4 |
| L2 | `SKILL.md` 36줄 | 애니메이션 속성 제한은 예산과 무관하다는 1문장 — 원칙 10(b) |
| L3 | `SKILL.md` 173줄 | "접근성 전체는 preflight §1에서" 1문장 — 원칙 10(a) |
| L4 | `SKILL.md` 131줄 | 4단계 진입 전 6줄 요약 지시 — 원칙 7 |
| L5 | `layout.md` §4 / `preflight.md` §2 | `100vw` 금지 · 이미지 그리드 트랙 `minmax(0,1fr)` · 이중 sticky 금지 · LCP `loading="lazy"` 금지 — 원칙 10(c) |
| L6 | `cursor.ts` 30줄 | references 를 `.cursor/rules/` 밖(`.designpaca/`)으로 |
| L7 | CLI 빌드 | 본문의 `references/*.md` 링크 존재 검증을 패키징 전 게이트로 |

---

## 7. 확인 못한 것

- **Cursor 에서 Skills 와 `.mdc` Rules 가 동시에 있을 때의 우선순위** — 공식 문서에 명시가 없다. R4 를 적용하면 `.cursor/skills/designpaca/` 와 `.cursor/rules/designpaca.mdc` 가 공존할 수 있는데, 중복 로드되는지 하나가 이기는지 확인되지 않았다. 둘 중 하나만 설치하도록 CLI 가 배타 선택을 강제하는 편이 안전하다.
- **`~/.codex/skills/` 가 실제로 Codex 의 사용자 스킬 스캔 경로인지** — 디렉터리 구조상 거의 확실하나(Codex 가 `.system/` 을 관리), 공식 문서 근거가 없고 실제 발동 테스트는 하지 않았다. Codex 를 띄워 `/designpaca` 가 뜨는지 한 번 확인하면 결론이 난다.
- **Windsurf 실제 동작** — `.windsurf/rules/*.md` 의 `trigger: model_decision` 동작을 실기로 확인하지 않았다. 문서(docs.devin.ai, 리다이렉트 후) 기준이다.
- **본문 토큰 수 정확값** — 4,600은 한글 1자≈1토큰 가정의 보수적 추정이다. 실제 토크나이저 기준으로는 더 적을 수 있다. 5,000선에 붙는 판단이 걸려 있으므로 `/context` 나 `/doctor` 로 실측하기를 권한다.
- **`references/motion.md`** — 미작성. 파이프라인 4-4가 이 문서를 지목하고 참조 지도(230줄)에도 등재되어 있다. 작성 완료 시 F1의 경로 치환 대상에 자동 포함된다.

---

# §3. F1~F5 반영 재검증

검증 시점: 2026-08-20. `packages/core/src/targets/` 6개 파일 + `SKILL.md` + `tokens.md` + `preflight.md` 정독.

## 3.0 통과한 것

| 확인 항목 | 결과 |
|---|:---:|
| `types.ts` 의 `TargetId` 에 `"windsurf"` 추가됨 | O |
| `index.ts` 의 `ADAPTERS` 에 `windsurf` 등록됨 | O |
| `installer.ts:81` 이 `plan.blocked` 를 throw 한다 | O |
| Windsurf 상한 검사가 **경로 재작성 후** 길이로 이뤄진다 (45줄 생성 → 59줄 검사) | O |
| `REF_PREFIX` 세 개 모두 `references/` 를 포함하지 않아 이중 치환이 없다 | O |
| `agents-md.ts` 가 `skillMd` 를 재작성해서 `skillDirActions` 에 넘긴다 | O |
| `agents-md.ts` 의 `detect` 가 `AGENTS.md` 실존으로 좁혀졌다 | O |
| user 스코프 refRoot 의 `reference` 중복이 제거됐다 (`~/.designpaca/skill`) | O |
| `cursor.ts` 에서 Windsurf 감지·라벨이 분리됐다 | O |
| 성능 예산 값이 세 문서에서 충돌하지 않는다 (전수 grep) | O |
| `tokens.md` 5장에 "이 표가 유일한 원본" 선언 + 5단계 열 추가 | O |
| `preflight.md` 2장이 실측 열만 갖는다 | O |
| 하드 게이트 2·3·11 이 검증 가능한 형태로 교체됐다 | O |

게이트 11은 내가 제안한 것보다 나은 형태로 들어갔다. `{{SETUP_TIME}}` 같은 **명시적 placeholder** 를 허용하고 그것을 6단계 `design.md` 미확정 목록으로 넘기는 구조는, 단순히 대시로 바꾸는 것보다 추적이 된다. 게이트 4도 "정의 없이 섹션마다 다른 것이 실패"로 좁혀져 리듬으로 의도한 테마 반전이 오탐되지 않는다.

`preflight.md` 0장에 새로 들어간 두 줄은 실측에서 나온 것으로 보이고 둘 다 정확하다:

> **React·Vue·Astro 등 프레임워크 프로젝트 → 프로덕션 빌드 결과에 돌린다.** 소스만 보면 렌더된 DOM 이 없어 대비·가로 스크롤·LCP 를 잴 수 없다.

> grep 검사는 **주석과 문자열을 제외**해라. "100vh 금지"라고 쓴 주석이 게이트 #9 에 걸리는 오탐이 실제로 나왔다.

---

## 3.1 V1 — F1 이 절반만 고쳐졌다 (참조 파일 내부 상호 링크)

`rewriteRefPaths` 는 **본문(`body` / `skillMd`)에만** 적용된다. `referenceActions`(common.ts 26~37줄)와 `skillDirActions`(9~23줄)는 `skill.files` 를 **그대로 복사**한다.

참조 파일 안에도 스킬 루트 기준 링크가 4곳 있다:

| 파일:줄 | 내용 |
|---|---|
| `references/layout.md:70` | "`references/antipatterns.md` 의 한글 조판 섹션을 읽어라" |
| `references/preflight.md:5` | "슬롭 지문 검출과 자가 채점표는 `references/antipatterns.md` 에 있다" |
| `references/preflight.md:35` | "`references/antipatterns.md` 의 grep 목록을 소스에 돌린다" |
| `references/tokens.md:143` | "상세는 `references/motion.md`" |

Cursor·Windsurf·AGENTS.md 설치본에서 이 네 곳은 프로젝트 루트 기준 `references/antipatterns.md` 를 가리키고, 그 경로에는 아무것도 없다. **본문은 고쳐졌는데 참조 파일끼리는 여전히 끊긴다.**

특히 `preflight.md:35` 가 아프다. 5단계 기계 검사 B가 antipatterns 의 grep 목록을 여는 지점인데, 그게 실패하면 슬롭 검출이 통째로 건너뛰어진다.

**수정안** — `common.ts` 의 두 함수가 파일 내용도 재작성하게 한다.

```ts
export function skillDirActions(root: string, skill: SkillSource, refPrefix?: string): FileAction[] {
  const rw = (s: string) => (refPrefix ? rewriteRefPaths(s, refPrefix) : s);
  const actions: FileAction[] = [
    { kind: "write", path: path.join(root, "SKILL.md"), content: rw(skill.skillMd) },
  ];
  for (const [rel, content] of skill.files) {
    actions.push({ kind: "write", path: path.join(root, ...rel.split("/")), content: rw(content) });
  }
  actions.push({ kind: "write", path: path.join(root, ".designpaca_version"), content: `${skill.version}\n` });
  return actions;
}
// referenceActions 도 같은 방식으로 refPrefix 를 받는다
```

호출부:

- `claude-code.ts` / `codex.ts` — `refPrefix` 를 넘기지 않는다(스킬 디렉터리 통째 복사라 상대 경로가 맞다)
- `cursor.ts:46` — `referenceActions(refRoot, ctx.skill, REF_PREFIX)`
- `windsurf.ts:49` — 동일
- `agents-md.ts:53` — `skillDirActions(refRoot, ctx.skill, refPrefix)` 로 바꾸고, 지금 인라인으로 하는 `skillMd` 재작성(54~56줄)은 제거한다(함수가 처리한다)

---

## 3.2 V2 — 단순 치환이 오작동한다 (`research/references/`)

팀 리드가 물어본 항목이다. **오작동할 여지가 있다.**

`replaceAll("references/", prefix + "/references/")` 는 문자열이 어디에 있든 자른다. 프로젝트 안에 이미 그런 문자열이 있다:

```
> 근거: research/references/04-ai-slop-signatures.md, 03-trends-2026.md (조사일 2026-08-20)
```

이 "근거" 줄은 **6개 참조 파일 하단에 각 1개씩** 있다: `antipatterns.md:271`, `galleries.md:163`, `layout.md:113`, `preflight.md:129`, `reference-method.md:240`, `tokens.md:194`.

치환하면 이렇게 망가진다:

```
research/.cursor/rules/designpaca/references/04-ai-slop-signatures.md
```

**지금은 터지지 않는다.** 참조 파일이 재작성 대상이 아니기 때문이다. 그러나 **V1 을 고치는 순간 정확히 이 6곳이 깨진다.** SKILL.md 본문에 `research/references/` 가 한 번이라도 들어가도 마찬가지다.

SKILL.md 본문은 지금 깨끗하다. 파일 경로가 아닌 `references/` 등장이 0곳임을 실측으로 확인했다.

**수정안** — 앞 경계를 명시한다.

```ts
/**
 * 본문의 `references/...` 상대 경로를 실제 설치 위치로 바꾼다.
 *
 * 앞에 경로 세그먼트가 붙은 것은 우리 참조가 아니다 — 각 참조 파일 하단의
 * `research/references/...` 근거 줄이 그렇다. 단순 치환하면 그것까지 망가진다.
 */
export function rewriteRefPaths(body: string, prefix: string): string {
  return body.replace(/(^|[^\w./-])references\//g, (_m, lead: string) => `${lead}${prefix}/references/`);
}
```

실제 문자열로 검증했다:

| 입력 | 출력 |
|---|---|
| "- 어디서 찾는가 → `references/galleries.md`" | "`.cursor/rules/designpaca/references/galleries.md`" 정상 |
| "> 근거: research/references/04-ai-slop-signatures.md" | **변경 없음** 정상 |
| "상세는 `references/motion.md`." | 정상 |
| 표 셀 안의 "`references/presets/editorial.md`" | 정상 |
| 줄 시작 "references/tokens.md 로 시작하는 줄" | `^` 앵커로 매치, 정상 |

회귀 테스트에 `research/references/` 케이스를 추가하기를 권한다. V1 수정과 함께 들어가야 한다.

---

## 3.3 V3 — AGENTS.md 포인터 블록의 강도

팀 리드 질문: "에이전트가 실제로 SKILL.md 를 열게 만들 만큼 충분한가."

**구조는 맞다.** 조건절("UI 를 새로 만들거나 다시 디자인할 때는")이 무관한 대화에서 무시되게 하고, 순서 제약("마크업·스타일을 쓰기 전에")이 늦게 읽는 것을 막고, 경로가 구체적이다. AGENTS.md 는 항상 로드되므로 조건절 없이 쓰면 매 대화에서 노이즈가 된다. 지금 형태가 옳다.

**약한 지점 두 개.**

**(a) 읽지 않았을 때의 결과가 없다.** SKILL.md 자신은 결과를 말한다 — "1단계를 건너뛴 디자인은 5단계에서 실패 처리한다"(32줄), "세 줄을 못 쓰면 아직 작업을 시작할 수 없다"(52줄). 포인터에는 그런 문장이 없어서 "권고"로 읽힌다. 스킬은 호출 메커니즘이 받쳐주지만 AGENTS.md 포인터는 지시 준수만으로 버틴다. 결과 문장 하나가 그 차이를 메운다.

**(b) 안에 무엇이 있는지 모른다.** "파이프라인(0~6단계)"만으로는 여는 값어치를 판단할 근거가 없다. 원칙 1이 참조 파일에 목차를 요구하는 것과 같은 논리다. 목차는 여는 비용을 낮추는 게 아니라 **여는 이유**를 준다.

**수정안** — `agents-md.ts` 40~50줄. 약 400B → 약 700B (32KiB 예산의 2%).

```ts
const block = [
  "## designpaca — 웹 디자인 파이프라인",
  "",
  "UI 를 새로 만들거나 다시 디자인할 때는, 마크업·스타일을 쓰기 전에",
  `\`${refPrefix}/SKILL.md\` 를 읽고 그 파이프라인(0~6단계)을 따른다.`,
  "**읽지 않고 만든 화면은 이 프로젝트의 토큰 규약과 감사 기준을 통과하지 못한다.**",
  "",
  "안에 있는 것 — 규모 판정(전체/연장/국소) · 레퍼런스 조사법 · 디자인 토큰과 성능 예산 ·",
  "미학 프리셋 4종 · 슬롭 지문 목록과 grep · 출시 전 하드 게이트 12개.",
  "",
  "- 프로젝트 루트에 `design.md` 가 있으면 그것이 최상위다. 스킬 기본값을 덮는다.",
  `- 참조 문서는 \`${refPrefix}/references/\` 에 있다. 각 단계가 지시하는 것만 그때 연다.`,
  "",
  `<!-- designpaca v${ctx.skill.version} — \`npx designpaca update\` 가 관리한다. 직접 고치면 업데이트가 멈춘다. -->`,
].join("\n");
```

부수: 현재 43줄의 "이 리포에서" 는 user 스코프(`~/.codex/AGENTS.md`)에서는 리포가 아니다. 위 안에서는 그 표현을 뺐다.

---

## 3.4 V4 — Windsurf 어댑터 스펙 대조

`03-format-specs.md` 5장과 전 항목 일치한다.

| 스펙 | 문서 근거 | `windsurf.ts` | 판정 |
|---|---|---|:---:|
| 경로 | `.windsurf/rules/*.md` (legacy) / `.devin/rules/*.md` (권장) | `.windsurf/rules/designpaca.md` | O |
| 확장자 | `.md` (`.mdc` 아님) | `.md` | O |
| 프론트매터 키 | `trigger`, `globs` | `trigger`, `description` | O (아래 주) |
| trigger 값 | `always_on` / `model_decision` / `glob` / `manual` | `model_decision` | O |
| 워크스페이스 상한 | 12,000자/파일 | 12,000 하드, 초과 시 `blocked` | O |
| 글로벌 상한 | 6,000자 | (글로벌 미지원) | 해당 없음 |

**`description` 키에 대한 주의.** 내가 fetch 한 문서의 프론트매터 예시는 `trigger` 와 `globs` 만 보여준다. `model_decision` 모드 설명이 *"Description shown always; full content retrieved when Cascade deems relevant"* 이므로 description 필드는 이 모드의 전제이고 커뮤니티 예시들도 이 조합을 쓴다. **다만 공식 예시로 확인하지는 못했다.** 실기 확인 전까지는 "근거 있는 추정"으로 두는 게 정확하다.

현재 규칙 파일 최종 크기는 **9,061자**(경로 재작성 후, 헤더 포함) / 상한 12,000. 여유 2,939자. V1 수정으로 참조 파일도 재작성되더라도 규칙 파일 본문은 변하지 않으므로 이 값은 그대로다.

**`.devin/rules/` 병행 배치는 지금 하지 않는 게 맞다.** 문서가 `.windsurf/rules/` 를 legacy 로 표기하긴 하나 여전히 읽고, 두 곳에 쓰면 규칙이 두 번 적용될 수 있다.

---

## 3.5 V5 — description YAML 인용 (R6 미적용, 유지 권고)

`cursor.ts:33` 과 `windsurf.ts:40` 이 여전히 인용부호 없이 쓴다.

```ts
`description: ${ctx.skill.description}`,
```

현재 description 값(320자)에는 콜론+공백도 `#` 도 없어 **지금은 유효한 YAML 이다**(실측 확인). 그러나 원칙 3 수정안대로 배제 조건 문장을 넣으면 콜론이 들어갈 확률이 크게 오른다. 깨지면 Cursor·Windsurf 가 **조용히 규칙을 무시한다** — 에러가 나지 않아 알아채기 어렵다.

```ts
`description: ${JSON.stringify(ctx.skill.description)}`,
```

JSON 문자열은 YAML 의 유효한 double-quoted scalar 이므로 그대로 쓸 수 있다. 두 줄 고치면 끝난다.

---

## 3.6 V6 — 본문이 5,000토큰 선을 넘었다

F3~F4 반영 후 실측:

| 시점 | 줄 | 문자 | 추정 토큰 |
|---|---:|---:|---:|
| 감사 시작 | 235 | 7,271 | 약 4,600 |
| **F1~F5 반영 후** | **232** | **7,938** | **약 5,024** |

Claude Code 의 컴팩션 재부착 예산은 스킬당 앞 5,000토큰이다. **지금 선을 막 넘었다.**

추정치는 보수적이다(한글 1자를 1토큰으로 계산). 실제 토크나이저에서는 더 적게 나올 수 있다. 그래도 여유가 사라진 것은 사실이고, 4장의 원칙 8 블록(+14줄, 약 +300토큰)을 넣으면 확실히 넘는다.

넘으면 잘리는 것은 문서 **끝** — 참조 문서 지도 표와 "작업 중 지켜야 할 것" 섹션이다. 치명적이진 않지만(각 단계가 참조 파일을 인라인으로 지목하므로) 관리해야 한다.

**확보 방안 — 참조 문서 지도 표를 압축한다.** 216~233줄 표는 각 단계가 이미 인라인으로 하는 말을 반복한다. 표를 지우고 4줄로:

```markdown
## 참조 문서 지도

전부 `references/` 에 있다. **각 단계가 지시할 때 그것만 연다.**
1단계 `galleries.md` `reference-method.md` · 2단계 `presets/README.md` + 고른 프리셋 1개 · 3단계 `tokens.md` `antipatterns.md`(한글 조판) ·
4단계 `layout.md` `svg-filters.md` `three.md` `motion.md` `experimental-canvas.md` · 5단계 `preflight.md` `antipatterns.md`
```

약 13줄 절약(약 250토큰). 원칙 1의 인덱스 요건은 유지된다 — 어떤 파일이 있고 언제 읽는지가 여전히 한눈에 보인다.

`/context` 나 `/doctor` 로 실측하기를 권한다. 내 추정보다 낮게 나오면 표를 유지해도 된다.

---

## 3.7 V7 — M1(가로 스크롤 폭)이 아직 열려 있다

R7 권장 항목이라 미적용이 예상 범위이지만, 하드 게이트와 직결되므로 다시 올린다.

| 위치 | 값 |
|---|---|
| `SKILL.md:174` 하드 게이트 5 | `320~1920px 사이 어느 폭에서든` |
| `references/preflight.md:88` | `375px 폭에서 가로 스크롤 없음` |
| `references/layout.md:109` | `모바일 폭(375px)에서 가로 스크롤이 없다` |

하드 게이트는 "오버라이드 없음"이라고 선언한 목록인데 참조 문서 두 곳이 **더 느슨한 기준**을 준다. 모델이 375px 만 확인하고 게이트를 통과 표시할 근거가 문서 안에 있다. 320px 으로 통일하면 된다(iPhone SE 세로 폭이 320px 이고, 그 아래가 뚫린 채 남는다).

---

# §4. 원칙 8 설계안 — 규모별 경로 분기

## 4.1 문제

지금은 모든 브리프가 0~6 전 단계를 통과한다. "이 버튼 색 좀 바꿔줘"에 갤러리 3곳 조사와 프리셋 선택과 리스크 결정을 요구하면, 모델은 **스킬 전체를 무시하는 법을 배운다.** 한 번 무시하면 하드 게이트도 같이 사라진다.

반대 방향도 실패다. 경로를 쉽게 열어주면 전부 짧은 쪽으로 도망가고, 그러면 핵심 규칙 1("레퍼런스 없이 시작하지 않는다")이 무력해진다.

## 4.2 선행 사례에서 가져온 것

**Hallmark — 신호 발화(signal firing).** 규모를 "판단"하게 하지 않고 **사실 신호의 발화 여부**로 라우팅한다.

> **Route to component-scope** if any signal fires:
> - Brief names a single UI element (button, card, modal, etc.)
> - Brief is ≤30 words referencing one element
> - Target file is a single component
> - User says "just the X," "only the Y," "this one element"
>
> — Nutlope/hallmark `skills/hallmark/SKILL.md`

이것이 핵심 발명이다. **"작은 작업인가?"는 모델이 자기에게 유리하게 답할 수 있고, "새로 만드는 화면이 있는가?"는 사실이다.** 팀 리드가 요구한 "자의적 선언 방지"의 답이 여기 있다.

Hallmark 는 경로마다 무엇이 남는지도 명시한다. component-scope 는 macrostructure·nav/footer archetype·hero enrichment 를 건너뛰지만 **8가지 상태(default/hover/focus/active/disabled/loading/error/success)는 오히려 더 강하게 요구**한다. 축소가 아니라 **초점 이동**이다.

**design-taste-frontend — 모드 감지를 첫 행동으로.**

> ### 11.A Detect the Mode (first action)
> * **Greenfield** / **Redesign - Preserve** / **Redesign - Overhaul**
> If ambiguous, ask **once**: *"Should this redesign preserve the existing brand, or are we starting visually from scratch?"*

모드를 **가장 먼저** 정하고, 애매하면 딱 한 번 묻는다.

**artifact-design — 트리트먼트 보정과 기본 방향.**

> **Calibrate treatment, not whether to design.** ... **When unsure: a well-composed page is never the wrong answer; an over-designed visual identity sometimes is.**

**단 designpaca 는 기본 방향을 반대로 잡아야 한다.** artifact-design 의 주된 실패는 과잉 디자인이지만, designpaca 는 이미 핵심 규칙 3("화려함은 4순위")과 4("대담함은 한 곳에만")로 과잉을 막아뒀다. designpaca 의 주된 실패는 **레퍼런스 없이 기본값에서 시작하는 것**이다(핵심 규칙 1). 그러므로 **애매하면 긴 경로**로 기울어야 한다.

## 4.3 결정 1 — 분기 기준

세 개의 **사실 질문**으로 판정한다. 셋 다 파일을 보면 답이 나오고 모델이 해석으로 뒤집을 여지가 없다.

```
A. 없던 화면을 새로 만드는가?
B. 토큰 체계(색 역할·타입 스케일·간격 리듬·모션 문법)를 새로 정하거나 다시 정의하는가?
C. 프로젝트에 design.md 가 있는가?
```

**왜 이 셋인가.**

- **A(새 화면)** — 셀 수 있다. "기존 페이지에 섹션을 추가"는 화면을 새로 만드는 게 아니므로 아니오다. 그 경우는 아래 섹션 상한이 잡는다.
- **B(토큰 체계)** — 이것이 진짜 경계다. 토큰을 정의·재정의하면 시스템 변경이고 페이지 전체에 파급된다. 기존 토큰 안에서 값을 쓰는 것은 적용이다. 그리고 "토큰 파일을 여는가"로 확인된다.
- **C(design.md)** — 방향이 이미 정해졌다는 파일 증거다. 있으면 1·2단계를 다시 돌 이유가 없고, 오히려 다시 돌면 §2 원칙 6에서 지적한 "지난번과 다른 디자인"이 발생한다.

**A·B 를 "규모", C 를 "이력"으로 나눈 것이 이 설계의 뼈대다.** 규모가 크면 방향이 필요하고, 이력이 있으면 방향은 이미 있다.

**섹션 상한을 하나 더 건다.** A·B 가 둘 다 아니오여도 "기존 페이지 전면 개편"이 국소로 새면 안 된다.

```
국소 경로 조건 — 아래를 전부 만족할 때만
- A 아니오 (새 화면 없음)
- B 아니오 (토큰 체계 재정의 없음)
- 손대는 섹션이 2개 이하
```

"섹션 2개 이하"는 셀 수 있고, 조작하려면 사실을 왜곡해야 한다.

## 4.4 결정 2 — 경로 3개와 각 경로에 남는 것

2개로는 부족하다. "design.md 가 있는 재작업"이 갈 곳이 없어진다. 그게 실무에서 가장 흔한 경우다(같은 사이트에 페이지 추가).

| 경로 | 조건 | 도는 단계 |
|---|---|---|
| **전체** | (A 또는 B) 이고 C 아니오 | 0 → 1 → 2 → 3 → 4 → 5 → 6 |
| **연장** | (A 또는 B) 이고 C 예 | 0 → 3 → 4 → 5 → 6 |
| **국소** | A·B 아니오, 섹션 2개 이하 | 0 → 4 → 5 → 6(추기) |

**어느 경로에서도 남는 것** — 팀 리드 직관대로 하드 게이트와 `design.md` 다. 여기에 판단 하나를 더한다.

| 항목 | 전체 | 연장 | 국소 | 근거 |
|---|:---:|:---:|:---:|---|
| 하드 게이트 12개 | O | O | O | 버그 검사지 미학 검사가 아니다. 버튼 하나를 고쳐도 대비 4.5:1은 지켜야 한다 |
| 접근성(38줄) | O | O | O | 이미 "어떤 브리프보다 우선"이라 경로와 무관하다. **경로별로 다시 쓰지 않는다** — 쓰면 오히려 "경로마다 다를 수도 있나"로 읽힌다 |
| 토큰 경유 | O | O | O | 게이트 1번이 이미 커버한다 |
| `design.md` | 작성 | 갱신 | **한 줄 추기** | 국소마다 전체를 다시 쓰는 것도 과잉이다 |
| 카운트 규칙 | O | O | **손댄 부분만** | 섹션 2개를 고치면서 페이지 전체 eyebrow 를 세는 것은 범위 밖이다. 다만 **내가 추가한 것이 기존 카운트를 넘기게 만드는지**는 본다 |
| 레퍼런스 조사(1단계) | O | X | X | 연장·국소는 `design.md` 가 그 자리를 대신한다 |
| 리스크 하나(2단계) | O | 상속 | X | 연장은 `design.md` 의 리스크를 이어받는다. 국소에는 리스크가 없는 게 맞다 |

**카운트 규칙을 국소에서 "손댄 부분만"으로 좁힌 것이 이 표에서 유일하게 논쟁적인 결정이다.** 전부 돌리자는 주장도 가능하다. 그러나 국소 작업마다 페이지 전체 레이아웃 패밀리를 다시 세게 하면 그 자체가 국소 경로의 존재 이유를 없앤다. Hallmark 가 component-scope 에서 macrostructure 를 아예 건너뛰는 것과 같은 판단이다.

## 4.5 결정 3 — 어디에 쓰나

**0단계 안, 브리프 3줄 다음.** 이유:

- 새 섹션으로 만들면 파이프라인이 8단계처럼 보인다
- 0단계 앞에 두면 "브리프 게이트보다 먼저 하는 것"이 되어 순서가 꼬인다. 규모는 브리프를 읽어야 판정된다
- 0단계는 이미 "브리프 게이트"다. 규모 판정은 게이트의 일부다

분량 목표 **14줄**. 3.6의 참조 지도 압축(-13줄)과 상쇄되어 순증이 거의 없다.

## 4.6 결정 4 — 오용 방지 5층

**(a) 판정을 사실 질문으로.** "작은 작업인가?"가 아니라 "없던 화면을 새로 만드는가?"다. Hallmark 의 신호 발화 방식.

**(b) 선언 + 근거 의무.** 경로를 고르면 어느 조건으로 골랐는지 한 줄로 말한다. 원칙 4의 "설명 의무"와 같은 구조이고, 사용자가 즉시 교정할 수 있는 지점을 만든다.

**(c) 기본값을 긴 쪽으로.** 애매하면 국소가 아니라 연장/전체.

**(d) 승급 규칙(escalation).** 조사한 어느 스킬에도 없는 장치이고, 실무에서 가장 자주 필요한 것이다. 국소로 시작했는데 작업 중에 조건이 깨지는 일은 흔하다 — 버튼 색을 바꾸려다 보니 토큰이 아예 없어서 새로 정의해야 하는 경우.

> 국소로 시작했다가 조건이 깨지면 그 자리에서 멈추고 경로를 올린다. **올렸다고 말해라. 조용히 국소에 머무는 것이 이 스킬의 최대 실패다.**

**(e) 반대 방향 오용도 막는다.** 국소 경로가 "선택"이면 모델은 안전하게 긴 경로를 고른다. 그러면 사용자가 스킬을 끈다. 국소 조건에 해당하면 **국소로 가는 것이 의무**여야 한다. 이 문장이 없으면 경로 분기가 작동하지 않는다.

## 4.7 SKILL.md 에 넣을 최종 문장

### (1) 0단계 — 브리프 3줄 코드블록 다음, "**막혔을 때**" 앞에 삽입

```markdown
**규모를 판정한다.** 셋 다 사실 질문이다. 추측하지 말고 파일을 보고 답해라.

- **A.** 없던 화면을 새로 만드는가?
- **B.** 토큰 체계(색 역할·타입 스케일·간격 리듬·모션 문법)를 새로 정하거나 다시 정의하는가?
- **C.** `design.md` 가 있는가?

| 조건 | 경로 | 도는 단계 |
|---|---|---|
| (A 또는 B) 이고 C 아니오 | **전체** | 0 → 1 → 2 → 3 → 4 → 5 → 6 |
| (A 또는 B) 이고 C 예 | **연장** | 0 → 3 → 4 → 5 → 6 — 방향은 `design.md` 가 이미 답했다 |
| A·B 둘 다 아니오, 손대는 섹션 2개 이하 | **국소** | 0 → 4 → 5 → 6(한 줄 추기) |

고른 경로와 근거를 한 줄로 말해라: *"국소 — 새 화면 없음, 토큰 재정의 없음, 섹션 1개."*

**애매하면 긴 쪽으로.** 단 국소 조건에 해당하면 국소로 가라 — 버튼 하나에 갤러리 3곳을 여는 것은 사용자가 이 스킬을 끄게 만든다.
**국소로 시작했다가 조건이 깨지면 멈추고 올린다.** 토큰을 새로 정의하게 됐거나, 손댄 섹션이 3개를 넘었거나, 방향을 바꿔야 하면. **올렸다고 말해라. 조용히 국소에 머무는 것이 이 스킬의 최대 실패다.**
```

### (2) 파이프라인 도입부 42줄 — 교체

건너뛰기를 허용하되 순서는 고정임을 명시한다. 지금 문장("순서를 바꾸지 마라")과 경로 분기가 정면 충돌한다.

```markdown
일곱 단계다(0~6). 0단계에서 정한 경로에 따라 **일부 단계를 건너뛸 수는 있지만, 도는 단계의 순서는 고정이다.** 각 단계에는 통과 조건이 있고, 통과하지 못하면 다음 단계로 가지 않는다.
```

### (3) 핵심 규칙 1번 32줄 — 교체

지금 문장은 연장·국소 경로를 자동으로 실패시킨다.

```markdown
1. **레퍼런스 없이 시작하지 않는다.** 전체 경로에서 1단계를 건너뛴 디자인은 5단계에서 실패 처리한다. 연장·국소 경로는 `design.md` 가 그 자리를 대신한다 — 그것도 없이 건너뛰면 실패다.
```

### (4) 1단계 제목 68줄과 첫 줄 70줄 — 교체

```markdown
### 1단계 — 레퍼런스 조사 (전체 경로 전용, **건너뛰기 금지**)

이 단계가 designpaca의 심장이다. 머릿속 기본값이 아니라 **실제로 존재하는 사이트**에서 시작한다. 연장·국소 경로는 0단계에서 이미 이 단계를 건너뛰기로 정했고, 그 근거는 `design.md` 다.
```

### (5) 2단계 통과 조건 109줄 — 한 줄 추가

```markdown
> 통과 조건: 한 문장 컨셉 + 프리셋 + 리스크 하나가 적혔다.
> **연장 경로는 이 단계를 돌지 않는다.** `design.md` 의 컨셉·프리셋·리스크를 그대로 이어받는다. 바꾸고 싶으면 전체 경로로 올린다.
```

### (6) 5단계 카운트 규칙 끝 193줄 뒤 — 두 줄 추가

```markdown
**국소 경로는 카운트를 페이지 전체로 다시 세지 않는다.** 내가 손댄 부분이 기존 카운트를 넘기게 만드는지만 본다.
하드 게이트 12개는 경로와 무관하게 전부 돈다.
```

### (7) 6단계 210줄 뒤 — 세 줄 추가 (기존 통과 조건 교체 포함)

```markdown
**국소 경로는 전체를 다시 쓰지 않는다.** `design.md` 끝에 한 줄만 추기한다 — `2026-08-20 · 무엇을 바꿨는지 · 토큰 변경이 있으면 그 값`. 기록 없는 국소 작업이 쌓이면 design.md 가 거짓말이 된다.

> 통과 조건: `design.md` 가 프로젝트 루트에 있다(국소면 추기됐다).
```

## 4.8 분량 정산

| 항목 | 증감 |
|---|---:|
| (1) 0단계 규모 판정 블록 | +14줄 |
| (2) 파이프라인 도입부 교체 | 0 |
| (3) 핵심 규칙 1번 교체 | 0 |
| (4) 1단계 제목·첫 줄 교체 | 0 |
| (5) 2단계 통과 조건 | +1줄 |
| (6) 5단계 카운트 단서 | +2줄 |
| (7) 6단계 국소 추기 | +3줄 |
| 3.6 참조 지도 압축 | **-13줄** |
| **합계** | **+7줄** |

232줄 → 239줄. 토큰은 약 5,024 → 약 5,050 근처. **여전히 선에 붙어 있다.** 참조 지도 압축을 반드시 함께 넣어야 하고, 그래도 `/context` 실측이 필요하다.

## 4.9 이 설계가 하지 않는 것

- **경로를 자동으로 결정하지 않는다.** 모델이 판정하고 선언한다. 자동 판정은 브리프의 뉘앙스를 놓친다.
- **국소 경로에서 품질 기준을 낮추지 않는다.** 하드 게이트·접근성·토큰 경유는 그대로다. 줄어드는 것은 **방향 결정 비용**뿐이다.
- **4번째 경로(예: 탐색/실험)를 만들지 않는다.** 실험은 `experimental-canvas.md` 가 이미 게이트로 다룬다. 경로가 4개가 되면 판정 자체가 부담이 된다.
