이 도구는 우리 글을 전형화한 AI 표본보다 더 나쁘게 채점했다. 원인은 AI 티가 아니라 우리 문장부호였다.
벤더링·계약·세 좌석 검증·기록이 끝났고, 첫 실제 산출물도 통과했다. 아래 수치는 프로브 텍스트와 업스트림 픽스처에서 나온 것이며, 실사용 결과는 06번 항목에 따로 적었다.
측정이 뒤집은 것
shim, LLM 호출 0회우리 글이 6점으로 가장 높다. 단위는 점이고, 이 점수는 판정이 아니라 경로 선택용이다.
원인은 번역투가 아니다
간섭 지수는 0.087로, AI 대조군 1.28의 15분의 1이다. 6점을 만든 것은 두 축 — 연결어미 직후 쉼표 z +5.84, 쉼표 포함률 z +2.80. 규칙 번호로는 C-11과 J-3이고, 실물로는 v11 응답 계약이 쓰는 쉼표와 대시다. 도구는 우리 문체를 잡아낸 것이다. 그래서 v11 출력은 고칠 대상이 아니라 적용 대상 밖으로 선언했다.
점수는 라우터지 판정이 아니다
업스트림이 의도적으로 나쁘게 만든 픽스처가 low로 나온 것이 신호였고, 코드가 이유를 말해준다. baseline_v2.json은 스스로를 캘리브레이션 대기 중인 placeholder라 선언하고, v1의 z는 실측된 분산이 아니라 인간과 AI의 평균 차의 절반을 1시그마로 친 값이다. 서로 무관한 450자 표본 둘이 모두 어휘다양성 z 약 +5를 낸 것도 같은 아티팩트다. 기록에 증거로 쓰는 것을 금지했다.
실제 값어치
최소 편집, 큰 이동4.8%만 고쳐서 위험도가 6점에서 2점으로 내려갔다. 단위는 %이며, 경고선의 6분의 1도 쓰지 않았다.
| 축 | 측정 | 판정 |
|---|---|---|
| P0 문자율 | 4.8% | OK |
| P1 연결어미 쉼표 | z +5.84 → −0.52 | 달성 |
| P1 쉼표 포함률 | z +2.80 → −1.52 | 과교정 |
| P3 골든 계약 | 수치·인용·격식 이상 없음 | PASS |
브레이크는 내가 쉼표를 지나치게 걷어낸 축 하나를 정확히 짚어냈다. 최종 판정은 WARN, 종료코드 1이다.
세 좌석 증명
주장이 아니라 실행업스트림은 결정론적 브레이크를 Claude 판에만 넣고, Codex와 Gemini 판에는 “30/50을 지켜라”는 프롬프트 약속으로 대체한다. 그것이 좌석의 한계인지 저자의 선택인지를 세 좌석에서 직접 실행해 갈랐다.
| 좌석 | L1 단일 콜 | 결정론적 게이트 | L2 진단 · L3 finalize |
|---|---|---|---|
| Claude | 가능 | 필수 | 가능 |
| Codex | 가능 | 필수 | 무수정 이식 불가 — 동일 호출 계약 없음 |
| Kimi | 가능 | 필수 | 불가 |
게이트는 좌석과 무관하다
브레이크는 파일 두 개를 읽는 평범한 파이썬 CLI다. 세 좌석이 수정 없는 같은 스크립트를 돌려 같은 문장, 같은 수치, 같은 종료코드(0/1/0)를 냈다. 그래서 래퍼는 게이트를 어느 좌석에서든 강제하고, 업스트림의 프롬프트 약속 대체를 받아들이지 않는다.
다단계는 이식되지 않는다
업스트림의 완전한 경로는 Claude의 Glob과 Agent 원시요소를 부르고, 업스트림은 그에 대응하는 Codex 어댑터를 제공하지 않는다. 다른 좌석에 그런 능력이 아예 없다는 뜻은 아니지만, 그 파일을 무수정으로 복사해 세 좌석 지원이라 부르면 거짓말이 된다. 이식 가능한 바닥은 L1 단일 콜 더하기 게이트이고, 올라가는 것은 Claude 좌석뿐이다.
Kimi는 업스트림이 아예 지원하지 않는다
설치기는 Claude, Codex, Gemini만 열거한다. 그럼에도 대상으로 받아들인 근거는 런타임에 네트워크 의존이 전혀 없다는 실측이다 — urllib, requests, httpx, socket, curl, WebSearch 어디에도 없다. Kimi의 검색 차단은 이 파이프라인과 무관하다.
실패한 테스트 하나
236건 중 2건번들 테스트 236건을 16분 돌려 2건이 실패했고, 둘은 같은 픽스처의 반복 실행이었다.
| 픽스처 | 회차 | 변경률 | 상한 | 판정 |
|---|---|---|---|---|
| fx_guard_overedit | run 0 | 64.9% | 50% | 초과 |
| fx_guard_overedit | run 1 | 60.0% | 50% | 초과 |
이 실패가 설계를 검증했다
이 픽스처는 업스트림이 “순진하게 전면 재작성하면 50%를 넘도록” 일부러 만든 텍스트다. 테스트는 실제 claude CLI를 부르고, 우리 좌석은 두 번 다 중단선을 넘겼다. 밀집된 AI 슬롭에서 모델의 자기 가드는 신뢰할 수 없다는 뜻이고, 게이트를 필수로 못 박은 이유가 바로 이것이다. 업스트림 CI는 이 실패를 보지 못한다 — CLI가 없으면 라이브 테스트를 통째로 건너뛰기 때문이다.
그래서 계약이 두 줄 바뀌었다
재시도 상한은 오너 결정으로 9회이며 10회에 닿지 않는다. 매 시도는 유료 호출 하나이므로 같은 방식의 반복은 금지하고, 시도마다 접근을 바꾼다. 그리고 비-Claude 좌석은 route_hint=heavy를 호출 전에 거절한다 — 올라갈 L2/L3가 없는 좌석에서 재시도는 같은 벽에 돈을 태우는 일이다.
구조
원본 무수정 + 바깥 계약| 층 | 내용 | 상태 |
|---|---|---|
| SKILL.md | 우리가 쓴 계약 — 좌석 층위, 호출 규칙, 게이트, 점수 의미, 적용 범위, 벤더 위생 | 135줄 |
| vendor/im-not-ai/ | 업스트림 추적 파일 전량, 한 글자도 고치지 않음 | 109파일 · 바이트 동일 |
| 업스트림 기본값 | 우리 계약 |
|---|---|
| cwd에 _workspace/ 생성 | --run-dir로 _tmp/feno-writer/ 고정 |
| Codex·Gemini는 게이트 생략 | 세 좌석 모두 게이트 필수, 종료코드로 판정 |
| 점수를 등급으로 제시 | route_hint 전용, 판정 금지 |
| 모든 텍스트 대상 | 한국어 산문만 — v11 응답·영어 통제면·오너 인용은 제외 |
| install.sh로 설치 | 실행 금지 — 핀 되지 않은 두 번째 사본이 깔린다 |
포크가 아니라서 따라갈 수 있다
업스트림은 도입 전날 v2.3.2를 냈을 만큼 활발하다. 규칙집만 발췌했다면 그 속도를 따라가지 못한다. 통째로 들여와 바깥에서 조이면, 새 버전이 나올 때 vendor/만 갈아끼우고 실측을 다시 돌리면 된다.
다음 확인할 것
순서대로-
실제 글 하나를 끝까지 통과시킨다
feno-posting 한국어 포스트 하나를 L1 더하기 게이트 경로로 돌리고, before/after와 종료코드를 남긴다. 08-23 11시대에 닫혔다. AA 인텔 브리핑을 소재로 한 한국어 설명문이 변경률 10.5%로 전 축 OK를 받았고, 동료 검토가 첫 판의 도식 결함을 잡아 두 번째 판에서 고쳤다.
-
호출 지점을 정한다
feno-posting 출력 단계 안에 넣을지, 초안이 나온 뒤 오너가 부르는 별도 패스로 둘지. 안에 넣으면 매 포스트가 유료 호출을 하나 더 태우고, 밖에 두면 쓰는 것을 잊는다.
-
실사용에서 첫 exit 2를 관찰한다
재시도 상한 9회 경로는 테스트 픽스처 밖에서 한 번도 돌지 않았다. 두 번 연속 초과가 이미 관측된 만큼, 9회가 도달 가능한 수인지 아니면 애초에 거절해야 하는 입력인지가 갈린다.
-
실행 산출물의 자리를 정한다
지금은 _tmp/feno-writer/에 쌓인다. 프로브만 있는 동안은 맞지만, 실제 배포되는 글의 before/after는 임시물이 아니라 증거다. 기록 수명 규칙에서 증거는 임시 전송물과 다른 자리를 갖는다.
-
조사용 클론을 정리할지 결정한다
_tmp/im-not-ai-probe-20260823/ 2.6MB는 벤더 사본이 생긴 뒤로 존재 이유가 없다. 오너가 보류했으므로 남겨둔 상태다.