# ponytail

> 별 9만 개짜리 룰셋에서 네 줄을 후보로 골랐는데, 근거가 버틴 건 한 줄이었습니다. 그리고 더 값나가는 건 제 룰셋 쪽에서 나왔습니다.

- 수치: 4줄 중 1줄
- 사람이 보는 화면: https://aitryed.com/ko/teardowns/harness/ponytail/
- 반대 언어: https://aitryed.com/en/teardowns/harness/ponytail/index.md
- 저장소: https://github.com/DietrichGebert/ponytail
- 이 사이트 안내(AI용): https://aitryed.com/ko/llms.txt

---

**「AI야, 일단 코드부터 만들지 마라」를 AI에게 상시 주입하는 규칙 묶음입니다. 「좋아요」가 9만 개 붙어 있습니다. 네 줄을 후보로 골랐는데 근거가 버틴 건 한 줄이었고, 이 조사가 실제로 찾아낸 건 남의 규칙이 아니라 «제 규칙의 자기모순»이었습니다.**

> **[도판]** 코드 도구가 아니라 프롬프트 배포 인프라다. 파는 것은 이 텍스트 한 장이고, 나머지는 그걸 스무 종의 호스트에 꽂는 배관이다.
>
> 일곱 칸짜리 사다리. 존재할 필요가 있나, 이미 있나, 표준 라이브러리가 하나, 플랫폼이 덮나, 설치된 의존성이 푸나, 한 줄로 되나를 차례로 묻고, 어느 칸에서든 걸리면 거기서 멈춘다. 일곱 번째 칸에 가서야 코드를 쓴다.

## 이 물건이 파는 것

AI에게 뭘 만들어 달라고 하면 **바로 코드를 씁니다.** 그게 문제일 때가 있습니다. 이미 있는 걸 또 만들거나, 쓸 필요 없는 걸 만듭니다.

그래서 이 규칙 묶음은 AI에게 **만들기 전에 사다리를 밟으라**고 시킵니다.

1. **안 만들어도 되나?**
2. **이미 있는 걸 쓰면 되나?**
3. 원래 있는 기능으로 되나?
4. 정말 없으면 그때 만든다

발상은 좋습니다. 그리고 제품의 실체는 **120줄짜리 텍스트 한 장**입니다. 나머지는 그 텍스트를 여러 AI 도구에 꽂아 주는 배관입니다.

## 열어 보니 「한 장」이 아니었습니다

작은 발견 하나. 「규칙 한 장」이 이 제품의 인상인데, 실제로는 **규칙이 세 군데에서 네 군데에 흩어져** 있었습니다.

정본이라고 부르는 파일 말고도 별도 규약 파일이 있고(도구 스무 종 중 절반 이상이 그쪽을 읽습니다), 예비용 사본이 있고, 보조 도구 다섯 개에도 규칙이 박혀 있었습니다.

특정 도구 하나만 쓰면 정본이 맞습니다. 그런데 **창고 전체로 보면 「한 장짜리」라는 인상과 다릅니다.**

## 간판 숫자가 정의를 바꿔치기했습니다

이 창고의 얼굴이 <strong>「코드량 54% 감소」</strong>입니다.

보고서와 설명서 둘 다 그 숫자를 <strong>「작업 단위 평균」</strong>이라고 선언합니다. 그래서 **그 선언된 정의대로 다시 계산해 봤습니다.**

<strong>−35.4%</strong>가 나왔습니다. 54%가 아닙니다.

즉 **자기가 밝힌 계산 방식과 자기가 내세운 숫자가 안 맞습니다.**

## 그런데 더 큰 문제는 「정답을 어떻게 쟀나」였습니다

숫자보다 이쪽이 심각합니다.

성능을 비교하려면 **「제대로 했는가」를 판정**해야 합니다. 그런데 이 비교에서 정답 판정 기준이 <strong>「코드를 한 줄이라도 썼는가」</strong>였습니다.

이러면 **아무것도 안 만든 쪽이 무조건 이깁니다.** 그리고 이 도구는 **「일단 만들지 마라」를 시키는 도구**입니다.

**재는 자와 시키는 것이 같은 방향입니다.** 그러면 그 비교는 처음부터 결과가 정해져 있습니다.

## 그래도 이 사람을 깎아내리면 틀립니다

공정하게 적어야 합니다. **이 저자는 이 분야 평균을 크게 웃돌게 정직합니다.**

| 한 일 |
|---|
| 자기 측정에 오염 버그가 있었던 걸 **스스로 찾아 공개**하고, 이전 결과를 **통째로 폐기** |
| **자기한테 불리한 데이터**를 그대로 실음 — 어떤 모델에서는 **오히려 느리다**, 다른 모델에서는 **비용이 38.7% 늘었다** |
| 측정 장치가 자가 점검에 실패하면 **돈 쓰는 걸 아예 거부하는 장치**까지 만들어 둠 |

두 번째가 특히 드뭅니다. **자기 제품이 느려지는 경우를 자기 보고서에 싣는 사람은 거의 없습니다.**

다만 하나가 걸립니다 — **틀린 방향이 전부 같은 쪽**이었습니다. 정직한데, **실수가 한 방향으로만 쏠려 있으면** 그건 우연이 아닐 수 있습니다.

## 네 줄 중 한 줄만 남았습니다

후보로 골랐던 네 줄 중 셋을 뺐습니다. 이유를 적어 둡니다.

| 뺀 것 | 왜 |
|---|---|
| **「이미 있나 확인해라」** | **자기네 비교 실험이 이 행동의 가치를 입증하지 못했습니다.** 이 도구를 쓴 쪽도 안 쓴 쪽도 둘 다 기존 것을 재사용했습니다 |
| **「기본 기능으로 되나 봐라」** | 효과가 **웹 화면 만들기에 몰려 있습니다.** 제 작업은 게임 엔진·자동화 쪽이라 해당 사항이 없습니다 |
| **「한 줄로 되면 한 줄로」** | **제 규칙이 이미 덮고 있습니다** — 「200줄이 50줄 되면 다시 써라」 |

남은 하나는 이겁니다.

> **고치기 전에 그 함수를 부르는 곳을 전부 찾아봐라.**

이게 왜 살아남았냐면, **이건 효과를 주장하는 문장이 아니라 절차를 지시하는 문장**이기 때문입니다. 효과 주장은 측정이 무너지면 같이 무너지는데, **절차는 무너질 게 없습니다.** 찾아보는 게 안 찾아보는 것보다 나쁠 일이 없습니다.

## 그런데 이 조사가 실제로 찾은 건 제 쪽에 있었습니다

여기가 이 편의 본론입니다.

통째로 도입할까 검토하면서 **제 기존 규칙과 부딪히는 곳**을 세어 봤습니다. 세 건이 나왔습니다.

그런데 그 과정에서 **더 큰 게 나왔습니다. 제 규칙이 이 도구와 상관없이 이미 자기모순 세 건을 안고 있었습니다.**

| 무엇에 대해 | 한쪽 규칙 | 다른 쪽 규칙 |
|---|---|---|
| 설정 옵션 | **요청 안 한 설정은 만들지 마라** | 조절값은 **기본값과 같아도** 설정으로 빼라 |
| 오류 처리 | **일어날 수 없는 상황에 처리 넣지 마라** | **항상 모든 단계에서 빠짐없이** 처리해라 |
| 미리 만들기 | **추측으로 미리 만들지 마라** | 테스트는 **세 종류 전부 필수**, 커버리지 80% |

**세 줄 다 정반대 말을 하고 있습니다.**

이런 건 **각각 볼 때는 안 보입니다.** 한 줄씩 읽으면 다 맞는 말입니다. **남의 규칙을 넣으려고 나란히 늘어놓으니 보였습니다.**

## 그래서 전역이 아니라 한 곳에만 넣었습니다

남은 한 줄을 어디에 넣을지도 **추측하지 않고 쟀습니다.**

결과가 나빴습니다. **전역에 넣으면, 시스템 설정을 통째로 바꾸는 하위 작업에도 그 지침이 살아서 넘어갑니다.** 그리고 **끄는 수단이 없습니다.**

그러면 테스트 케이스 만드는 작업이나 QA 자동화에도 「일단 만들지 마라」가 걸립니다. 그 작업들은 **만드는 게 목적**인데요.

그래서 **전역이 아니라 담당자 하나에만** 넣었습니다.

## 여기부터는 자세한 기록입니다

**간판 수치는 무너졌고, 채택은 한 줄입니다.** 이 레포의 얼굴인 "코드량 −54%"는 보고서 자신이 선언한 정의로 다시 계산하면 −35.4%이고, 애초에 **정답 판정 게이트가 없습니다** — 「코드를 한 줄이라도 썼는가」가 정답 여부입니다. 후보 네 줄 중 근거가 버틴 건 **"모든 호출부를 grep하라"** 하나뿐이었고, 그마저 전역이 아니라 에이전트 하나에만 넣었습니다. 그리고 이 조사가 실제로 찾아낸 건 남의 룰셋이 아니라 **제 룰셋의 자기모순 세 건**이었습니다.



## 무엇을 파는 물건인가

**에이전트에게 「일단 만들지 마라」를 상주 주입하는 프롬프트 룰셋이다.** 코드를 검사하거나 고치는 도구가 아니다 — 제품의 실체는 위 사다리를 포함한 **120줄짜리 텍스트 한 장**이고, 레포의 나머지는 그 텍스트를 스무 종의 에이전트 호스트에 꽂고 최신으로 유지하는 배관이다.

별 **92,133개**, 포크 5,069개, npm 주간 9,166 다운로드. 개설 7주.

사다리에 붙은 조건이 둘 있는데 이게 이 룰셋을 단순한 "적게 만들기"와 가른다.

- **사다리는 문제를 이해한 뒤에 돈다** — 순서를 바꾸면 그냥 대충 하는 것이 된다
- **게으름은 해답을 줄이는 것이지 읽기를 줄이는 게 아니다** — 버그 수정은 "증상 아닌 근본원인, 모든 호출부 grep"으로 못 박혀 있다

**잘라내기 금지 목록**도 있다. 신뢰 경계 입력검증, 데이터 손실 에러핸들링, 보안, 접근성, 하드웨어 캘리브레이션 노브. 미니멀리즘이 위험해지는 자리를 스스로 표시해 둔 것이다.

### 뜯어보니 달랐던 것 둘

**룰 텍스트가 한 곳이 아니다.** 정본이라 부르는 파일 말고도 별도 규약 파일(스무 종 호스트 중 절반 이상이 이걸 읽는다), JS 폴백본, 보조 스킬 다섯 종에 룰이 흩어져 있다. **세 군데에서 네 군데다.** 특정 호스트로 한정하면 정본이 맞지만, 레포 전체로 보면 "한 장짜리 제품"이라는 인상과 다르다.

**강도 레벨은 실질 차이가 거의 없다.** lite / full / ultra 세 단계를 파는데, 실제 주입 텍스트가 5,202자 · 5,229자 · 5,267자다 — **차이가 65자, 1.2%.** 내용 차이가 아니라 수사(修辭) 차이다. full과 ultra의 실행 diff를 뜨면 **100줄 중 3줄**이고 그 3줄에 엣지케이스 처리를 줄일 문장은 없다.

## 간판 수치가 정의를 바꿔치기했다

<strong>"코드량 −54%"</strong>가 이 레포의 얼굴이다. 보고서와 README 둘 다 그 수치를 <strong>"태스크 단위 평균"</strong>이라고 선언한다.

공개된 12태스크 표로 직접 계산하면 태스크 평균은 <strong>−35.4%</strong>다. −54%는 기준선 코드량으로 **가중한 총합 비율**이다. 선언한 정의와 실제 계산이 다르다.

그리고 그 −54% 중 **17.7포인트가 날짜·색상 선택기 두 태스크에서 나온다.** 그 둘을 빼면 −36.5%, 백엔드 여섯 태스크만 보면 <strong>−22.2%</strong>다.

그런데 더 근본적인 문제가 따로 있다. **정확성 게이트가 없다.**

```python
sc = {"correct": 1 if stats.get("total_loc", 0) > 0 else 0, "safe": 1, "reason": "git-diff"}
```

`correct`는 <strong>"코드를 한 줄이라도 썼는가"</strong>이고 `safe`는 **하드코딩된 상수 1**이다. 23줄짜리 날짜 선택기가 티켓을 실제로 충족했다는 증거가 이 벤치마크 어디에도 없다.

저자는 이 구멍을 안다. 별도 스크립트를 만들어 놓고 주석에 *"가장 신빙성 있는 공격은 「덜 만들었으니 덜 썼다」이다"*라고 적어 뒀다. 그리고 **한 번도 보고하지 않았다.**

**계측기에도 결함이 있다.** 코드량을 셀 때 테스트를 소스에서 빼야 하는데, 판별 함수가 파이썬 관례와 특정 폴더명만 인식한다. 그래서 프론트엔드의 `*.test.tsx`가 **소스로 계산된다.** 하네스 스스로 *"테스트는 따로 세며 결코 군더더기로 치지 않는다"*고 선언해 놓고 한쪽 언어에서만 안 지켜지는데, **하필 대승 여섯 태스크가 전부 그 언어다.**

## 정직성은 진짜인데, 기울어진 방향이 전부 같다

이 레포를 깎아내리기 쉬운데 그러면 틀린다. 이 저자는 **오염 버그를 자진 발견해 공개하고 이전 결과를 통째로 폐기 처리**했고, 불리한 데이터를 실었다 — 백엔드에서 효과가 수렴한다는 것, 어떤 모델에서는 **오히려 느리다**는 것, 다른 모델에서는 **비용이 38.7% 늘었다**는 것. 계측기 자체가 자가 검증에 실패하면 **API 지출을 아예 거부하는 게이트**까지 만들어 뒀다. 이 분야 평균을 크게 웃돈다.

**그러니 무너지는 건 정직성이 아니다.** 무너지는 건 **집계 방식·계측기 선택·태스크 선정·미보고 항목 넷이 전부 같은 방향으로 기울어 있다**는 사실이다. 하나였으면 실수고, 넷이 같은 쪽이면 그건 결과가 나오는 구조다.

태스크 선정이 특히 그렇다. 사다리 4칸에 **네이티브 날짜 입력이 문자 그대로 예시로 적혀 있고**, 헤드라인 1위 태스크가 "날짜 선택기를 추가하라"다. 측정되고 있는 건 일반적인 미니멀리즘이 아니라 **그 한 문장의 리콜률**이다. 그리고 12태스크 중 **미니멀리즘이 손해를 보는 축**(접근성 요구, 하드웨어 캘리브레이션 같은 것)이 **0개**다.

안전 항목도 마찬가지다. README는 안전 태스크가 일곱 개라 하고 재현 명령도 일곱 개를 나열하는데, **보고서는 여섯 개만 싣는다.** 빠진 하나가 하필 저자가 **비판자에게 답하려고 만든 그 태스크**다.

원자료는 공개돼 있지 않다. 보고서가 광고하는 재채점 재현 경로가 **제3자에게는 실행 불가능하다.**

⇒ 방어 가능한 형태로 남는 주장은 이 정도다. *특정 소형 모델에서, 네이티브 HTML 입력으로 대체 가능한 프론트엔드 티켓에 한해, **검증되지 않은** 코드 산출량이 크게 준다.*

## 남은 한 줄 — 그리고 그게 왜 살아남았나

채택한 건 **"모든 호출부를 grep하라"** 한 줄이다.

레포 자체 벤치에 이런 태스크가 있다. 두 함수가 **같은 내부 출금 함수를 공유**하는데 버그 리포트는 한쪽만 지목하고, 채점기는 **리포트에 이름조차 없는 다른 쪽**의 초과 출금을 검사한다. 즉 "리포트에 적힌 것만 고치면 실패한다."

> **[도판]** 대조군이 있어서 이 한 줄만 살아남았다. 옮긴 것은 지시의 의미가 아니라 문장의 형태였다.
>
> 같은 지시를 문장 형태만 바꿔 넣었을 때의 정답률. 룰 없이는 여섯 번 중 한 번, 평문 산문으로 넣으면 세 번 중 영, 작업지시형 문장으로 넣으면 여섯 번 중 여섯이다.

**대조군이 결정적이다.** 뜻이 같은 평문 산문 — "흐름을 끝까지 추적하라" — 은 **세 번 중 영**이었다. 작업지시형 문장만 여섯 번 중 여섯으로 옮겼다.

이게 왜 이 페이지에서 유일하게 살아남았나. 앞에서 무너뜨린 건 전부 **코드량 축**의 집계 문제인데, 이 항목은 **품질 축**이라 그 문제가 적용되지 않는다. 그리고 찬반 두 방향의 리뷰가 정반대 결론을 내면서 **이 항목 하나에서만 독립적으로 수렴**했다.

한계도 같이 적는다. **레포 자체 벤치이고, 표본 6, 태스크 하나, 원자료 미공개.** 소형 모델에는 전이되지 않는다(기준선도 실패하는 천장 구간이다).

### 나머지 셋을 왜 뺐나

- **사다리 2칸(이미 있나)** — **레포 자체 벤치가 행동 가치를 입증하지 못했다.** 기준선과 ponytail 둘 다 헬퍼를 재사용했고, 중복 실패가 재현되지 않았다
- **사다리 4칸(플랫폼 네이티브)** — 효과가 HTML 폼 컨트롤 치환에 집중돼 있다. 제 작업은 게임 엔진 C#·파이썬 테스트·파이프라인 JS 위주라 해당 사항이 없다
- **원라이너 반사** — 제 규칙이 이미 덮고 있다("200줄이 50줄 되면 다시 써라")

## 조사가 찾아낸 건 남의 룰셋이 아니라 제 룰셋이었다

통짜 도입을 검토하면서 제 규칙과 부딪히는 지점을 세었다. 세 건이 나왔다. 그런데 **더 큰 게 나왔다 — 제 룰셋이 ponytail 없이도 이미 자기모순 세 건을 안고 있었다.**

| 축 | 한쪽 | 다른 쪽 |
|---|---|---|
| 설정성 | 요청 안 한 **설정성 금지** | 튜닝 노브는 **코드 기본값과 같아도** config 키로 뺀다 |
| 에러 처리 | **불가능한 시나리오에 에러 처리 금지** | **항상 포괄적으로, 모든 레벨에서** |
| 투기성 | **투기적인 것 금지** | 유닛·통합·E2E **전부 필수**, 커버리지 80% |

셋 다 상시 로드되고, **어느 쪽이 이기는지가 어디에도 정의돼 있지 않다.** 그러니 매 턴 모델이 임의로 정한다.

**조항을 더 얹기 전에 이 셋을 재정하는 게 순서다.** 그리고 아직 안 했다 — **이 조사가 만든 숙제가 이 조사가 가져온 한 줄보다 크다.**

## 그래서 전역이 아니라 에이전트 하나에만

"전역에 넣으면 어디까지 걸리나"를 추측하지 않고 쟀다. 결과가 나빴다 — **시스템 프롬프트를 통째로 교체하는 자식 프로세스에도 전역 지침은 살아서 넘어간다.** 전역에 넣으면 테스트 케이스 생성과 QA 자동화까지 예외 없이 걸리고, **끄는 수단이 없다.**

그쪽에서는 "덜 만들기"가 곧 커버리지 구멍이다. 특히 <strong>"답을 기본값으로 낼 수 있는 일에 절대 멈추지 마라"</strong>는 줄이, 기획서에 근거가 없으면 멈추고 「확인 필요」로 표기하라는 제 규칙을 정면으로 뒤집는다.

그래서 3단으로 좁혔다. **전역 ❌ → 프로젝트 ❌ → 게임 코드를 쓰는 에이전트 하나에만 ✅.** 프로젝트 단위도 기각인 이유는 격리가 안 되기 때문이다 — 같은 프로젝트의 QA 에이전트들이 함께 걸린다. 콘텐츠를 만드는 에이전트도 제외했다. 거기서는 **양이 곧 값**이고, 검증 쪽은 **하네스와 픽스처가 자산**이다.

그 하나에도 두 줄은 빼고 넣었다. <strong>"가능한 한 적은 파일"</strong>은 파일을 잘게 쪼개라는 제 규칙과 정면으로 부딪히고, <strong>"절대 멈추지 마라"</strong>는 불명확하면 멈추라는 첫 번째 규칙과 부딪힌다. **표적을 좁혀도 남는 충돌은 표적을 좁혀서 해결되지 않는다.**

⚠ 측정하면서 한 번 틀렸다. 전파 범위 프로브의 1차 결과는 "전역 규칙이 자식에 전달 안 됨"이었는데, **한 번에 두 가지를 물어서 생긴 오탐**이었다. 같은 질문으로 대조해 정정했다. **프로브는 한 번에 하나만 묻는다.**
