humanize-korean
AI(ChatGPT·Claude·Gemini 등)가 쓴 한글 텍스트를 "사람이 쓴 글처럼" 윤문해주는 오케스트레이터 스킬. 번역투·영어 인용 과다·기계적 병렬·관용구·피동태 남용·접속사 남발·리듬 균일성·이모지/불릿 과다 등 10대 카테고리 70개 AI 티 패턴을 탐지·분류해 내용은 한 글자도 건드리지 않고 문체·리듬·표현만 자연스러운 한국어로 재작성한다. shim의 route_hint(light|standard|heavy)로 경로를 정해 잘 쓴 글은 1콜, 표준은 2콜, 중증·장문만 3+콜(진단→겨냥 윤문→finalize)로 처리
By epoko77-ai · 470 installs
npx skills add epoko77-ai/im-not-ai --skill humanize-korean
Source repository · Upstream listing
Humanize Korean — AI 한글 티 제거 오케스트레이터 (v2.3)
v2.3.2 — 플러그인 스킬을 관례 위치(루트 skills/ )로 이동. 마켓플레이스 설치에서 shim·진단이 조용히 누락되던 경로 문제 해소.
v2.3.1 — 경로 해석·런타임 경계·계약 정합 수정 회차(외부 제보 반영). 기능 변경 없음.
v2.3.0 — 구조 수렴 게이트( verify gates.py 4축: 목표달성·대구 전멸·수치·golden) + 진단 슬림 인덱스( diagnosis rules.md , taxonomy 83%↓). (v2.2: route hint 3경로 + 단일 콜 우선)
버전 히스토리·실측 근거·테스트 시나리오: [ ${CLAUDE SKILL DIR}/references/design notes.md ](references/design notes.md)
Phase 0: 컨텍스트 확인 및 경로 결정
작업 시작 시 가장 먼저 다음 한 줄을 사용자에게 출력한다.
(경로는 Phase 1의 shim 실행 후에 확정되므로, 이 상태 줄은 shim 직후 출력한다.)
전 경로 공통 의미 앵커
윤문 전에 문장별 핵심 내용 명사·개념어 를 내부 목록으로 잡는다. 주어·목적어·보어에서 원문의 주장을 구성하는 어휘가 대상이다.
조사·어미는 바꿀 수 있지만, 내용 앵커의 원형 어휘는 결과에 최소 한 번 그대로 남긴다. 동의어 치환이나 문장 병합을 이유로 삭제하지 않는다.
AI 관용구·추상어를 덜어낼 때는 수식어와 형식명사만 걷어낸다. 내용 앵커까지 함께 사라질 것 같으면 해당 문장을 롤백한다.
출력 직전 원문과 윤문본을 다시 대조한다. 내용 앵커 하나라도 빠졌으면 자연성보다 의미 보존을 우선해 복원한다.
경로 결정 규칙
1. 사용자 명시가 최우선. strict ·"정밀 모드"·"정밀하게"·"제대로" → heavy 고정 . "가볍게"·"빠르게만" → light 고정 . 명시가 있으면 route hint는 무시한다.
2. 명시가 없으면 shim이 00 metrics.json 에 쓴 route hint ( light standard heavy )를 디폴트 경로로 따른다.
3. route hint 필드가 없거나 shim이 graceful degrade로 점수 산출에 실패한 경우 → standard 로 간주.
4. light/standard 결과가 등급 C/D → 사용자에게 "heavy(정밀) 재실행 권고" 안내(자동 전환 아님 — 사용자 opt in).
5. 입력 길이는 경로를 바꾸지 않는다. 1만자급도 단일 콜로 처리한다(§설계 노트의 실측 근거 참조). 길이·중증도 판단은 shim의 route hint에 위임한다.
run id 결정
모든 경로는 cwd 기준 . 새 폴더 생성도 cwd 기준 workspace/{YYYY MM DD NNN}/ 에 만든다.
기존 시퀀스 확인은 Glob 도구 로 표지 파일을 매칭해 간접 조회.
올바른 사용법: Glob(pattern=" workspace/YYYY MM DD /01 input.txt") → 결과에서 폴더명 추출 후 NNN 최댓값 + 1.
주의: Glob은 디렉토리 자체는 매칭하지 못한다. 반드시 그 안의 표지 파일( 01 input.txt )을 매칭할 것.
Bash ls 는 OS·셸 환경에 따라 경로 해석이 달라지므로 사용 금지.
당일 폴더가 없으면 NNN = 001. 있으면 마지막 NNN + 1.
부분 재실행 신호("이 카테고리만 다시"·"2차 윤문")일 경우 기존 run id 재사용 + heavy 경로로 자동 승급.
스크립트 경로 규칙 ( ${SKILL ROOT} )
스크립트는 절대경로로 부른다. cwd 기준 상대경로로 부르면 안 된다.
references/ 는 스킬 디렉터리 기준이라 ${CLAUDE SKILL DIR} 를 쓴다 — ${SKILL ROOT} 와 기준이 다르니 섞지 않는다. 룰북·taxonomy 경로도 맨앞 접두어 없이 쓰면 cwd 로 풀려 No such file or directory 가 난다.
scripts/ .py 는 설치 루트에 있고 cwd 는 사용자 작업 디렉터리다. 마켓플레이스 설치에서 둘은 절대 일치하지 않는다. 반면 workspace/ 같은 데이터 경로는 cwd 기준이다(run id 규칙 참조). 두 기준이 한 명령줄에 섞이므로 스크립트 쪽만 절대경로로 고정한다.
Phase 1 시작 전에 한 번 정한다.
.claude plugin/ 디렉터리를 만날 때까지 거슬러 올라간다. 고정된 횟수로 올라가지 않는 이유 는 스킬 위치가 배포 방식마다 다를 수 있어서다 — 고정 깊이는 레이아웃이 바뀌면 조용히 엉뚱한 곳을 가리킨다.
cd P 가 핵심이다. 심링크 설치( install.sh 기본)에서는 스킬 디렉터리가 저장소를 가리키는 심링크라, 그냥 cd 하면 셸이 논리 경로를 유지해 엉뚱한 곳(홈 디렉터리)으로 올라간다. P 로 물리 경로를 먼저 푼 뒤 올라가야 심링크·플러그인 양쪽에서 같은 답이 나온다. 이후 모든 스크립트 호출에 ${SKILL ROOT}/scripts/... 를 쓴다.
확인 : ls "${SKILL ROOT}/scripts/prepare monolith input.py" 가 실패하면 경로 유도가 틀린 것이다. 이 경우 스크립트를 찾을 때까지 임의로 추측하지 말고, 정량 shim·게이트 없이 진행한다고 사용자에게 알린 뒤 계속한다. 조용히 건너뛰면 route hint 와 철칙 4 게이트가 사라진 것을 아무도 모른다.
CLAUDE PLUGIN ROOT 는 Bash 도구 안에서 비어 있는 경우가 확인됐다( 84). 이 변수에 의존하지 않는다.
Phase 1: 입력 저장 + 정량 사전 점수 (input shim — 전 경로 공통)
1. cwd 기준 workspace/{run id}/ 생성
2. 입력 텍스트를 01 input.txt 에 저장
챗봇 잔재 위생 (v2.6) : 저장 전에 챗봇 프레임 문장이 섞여 있으면 벗겨낸다 — 머리("물론입니다!", "다음은 ~입니다:", "요청하신 내용을 정리하면"), 꼬리("도움이 되셨길 바랍니다", "추가 질문이 있으시면"), 지식 한계 면책("제 지식은 ~까지입니다"). 실사용자는 챗봇 출력을 그대로 붙여넣는 일이 많고, 이 문장들은 본문이 아니므로 제거해도 의미 손실이 0이다. 본문 안에 자연스럽게 녹아 있는 유사 표현은 건드리지 않는다.
3. 첫 300자로 장르 자동 추정 (사용자 명시 시 우선)
4. 사전 처리 shim을 Bash로 1회 실행:
genre 값은 영문 키: essay column report blog abstract (생략 시 essay ). 장르 힌트 매핑: 칼럼→ column , 리포트→ report , 블로그→ blog , 공적/기타→ essay .
run dir · diagnosis 의 상대 경로는 cwd 기준 으로 해석된다(위 run id 규칙과 동일 기준). 그 외 인자: text (run dir 없이 즉석 실행 시 새 run 디렉토리 자동 생성), baseline (baseline JSON 경로 override, 평소 불필요), diagnosis (진단 텍스트 파일을 점수 블록 앞에 prepend — standard·heavy의 진단 결합용).
산출: 00 metrics.json (정량 점수 + route hint ) + 01 input with metrics.txt (점수 블록을 원문 앞에 붙인 결합 파일).
graceful degrade 내장 : metrics 계산이 실패하면 shim이 점수 블록 없이 원문만 감싼 결합 파일을 쓰고 00 metrics.error 를 남긴다. 이 경우 route hint 없음 → standard 경로.
5. 00 metrics.json 의 route hint 를 읽어 Phase 0 규칙대로 경로를 확정하고 상태 줄을 출력한다.
단일 콜 우선 — 청킹은 여기서 하지 않는다. chunk 는 heavy 경로 전용이며, 그때도 청크 경로를 탈지는 shim이 실제로 청크를 2개 이상 만들었는지로 정한다(heavy 절 참조).
Light 경로 (1콜) — 잘 쓴 글
어휘 티가 거의 없고 구조 티만 미미한 글. 목표는 과윤문 방지 이지 많이 고치는 게 아니다.
1. 진단 생략. humanize monolith 를 Agent 도구로 1회 호출 — 청킹 없음.
입력: input path=01 input with metrics.txt , quick rules path=${CLAUDE SKILL DIR}/references/quick rules.md , genre hint , 그리고 강도 지시 보수 (내용 앵커 원형 보존, 원문에 없던 표현 삽입 금지, 확신 없는 구간은 그대로 둔다).
출력: final.md (본문 + <! HUMANIZE SUMMARY 블록).
2. Phase 2.5 변경률 게이트(Bash — LLM 콜 아님).
3. 조기 종료 보고 : monolith 탐지가 거의 없고 게이트 변경률이 5% 미만이면, 결과 전달을 "이미 좋은 글입니다 — 손댄 곳은 {N}곳({요지}) 정도"로 요약한다. 억지로 더 고치지 않는다.
4. 게이트 exit 2(≥50%)일 때만 롤백 재실행 1회(이 경우 총 2콜). light에서 50%가 나오면 과윤문 사고이므로 재실행 지시에 보수 강도를 재강조한다.
콜 수: 1 (게이트 실패 시 최대 2).
Standard 경로 (2콜) — 보통의 AI 초안
1. 진단 1콜 : humanize diagnostician 을 Agent 도구로 1회 호출.
입력: input path=01 input with metrics.txt , taxonomy path=${CLAUDE SKILL DIR}/references/diagnosis rules.md (진단 전용 슬림 인덱스 — 71패턴 전수, taxonomy에서 자동 생성)
출력: 02 diagnosis.md — 글 전체의 지배 패턴 3~6개 (본진 ID + 근거 + 처방) + 장르·격식 + 보존 지침.
진단은 span을 세지 않는다. "무엇이 이 글을 지배하는가"를 판단한다(안정적).
2. shim으로 진단을 monolith 입력 앞에 결합 (Bash — LLM 콜 아님):
→ 01 input with metrics.txt 가 [진단 → 정량 블록 → 원문] 순으로 재생성된다.
3. 윤문 1콜 : humanize monolith 1회 호출 — 청킹 없음. 1만자급도 단일 콜이다. → final.md .
4. Phase 2.5 변경률 게이트(Bash).
5. finalize 생략이 기본. 과윤문은 verify gates.py 의 결정적 게이트가 잡는다. finalize 승급 조건(아래 표)에 걸릴 때만 humanize finalizer 1콜 추가(이 경우 총 3콜).
콜 수: 2 (finalize 승급·게이트 롤백 시 3).
Heavy 경로 (3+콜) — 중증 AI 슬롭·검증 증적 필요
strict ·"정밀 모드"의 강제 대상. 진단→겨냥 윤문→finalize의 완전한 3콜 구조.
Phase P1: 진단
Standard의 1과 동일 — humanize diagnostician 1콜 → 02 diagnosis.md . 장문이라도 진단은 통짜 1콜(전 청크 공유)이다.
Phase P2: 겨냥 윤문
1. shim으로 진단 결합 (Bash). heavy에서만 chunk 를 함께 줄 수 있다:
분할 여부·경계는 100% shim(Python)이 정한다(문단·문장 경계, 헤딩 승격, 말미 각주 passthrough — 청킹 임계는 shim 관리).
산출: 01 chunk {NN} input with metrics.txt N개 + chunk manifest.json .
2. 청크 경로 판정 : chunk manifest.json 의 body 청크(passthrough 제외)가 2개 이상일 때만 청크 경로. 1개면 단일 monolith 콜로 처리한다 — 청킹은 shim의 결정이지 오케스트레이터의 추측이 아니다. 단일 콜로 처리할 때의 입력 파일도 manifest가 있으면 그 청크의 input file 값을, 없으면 01 input with metrics.txt 를 쓴다.
3. 단일 콜(기본) : humanize monolith 1회 호출( input path=01 input with metrics.txt ). monolith는 진단문을 앞머리에서 읽고 지배 패턴을 겨냥해 윤문한다. → final.md .
4. 청크 병렬(shim이 실제로 쪼갠 경우만) :
각 body 청크를 monolith로 병렬 호출 (동시 최대 4). 입력·출력 파일명은 manifest의 input file · rewritten file 필드를 그대로 사용한다 — 파일명을 직접 조립하지 않는다(인덱싱 불일치 사고 방지).
각 청크 콜은 같은 quick rules path (파일 참조)와 같은 02 diagnosis.md 를 공유한다. 룰북·진단 전문을 청크 프롬프트에 복붙하지 않는다 — 재로드 비용이 청킹 토큰 폭발의 주범이었다(§설계 노트).
재조립: python3 ${SKILL ROOT}/scripts/reassemble chunks.py run dir workspace/{run id} → 03 reassembled.md (passthrough 원문 삽입 + 문자수 대사). 이걸 final.md 로 삼는다.
청크 경계 문체 이음매가 어색하면 경계 전후 2문단만 monolith로 국소 패치(전역 재작성 금지 — 의미 드리프트 유발).
재청킹 주의 : chunk 재실행 시 경계가 바뀌므로 기존 02 chunk rewritten.txt 는 shim이 자동 삭제한다( stale removed ). 청킹 후 입력을 수정하면 재청킹부터 다시 한다.
Phase P2.5: 구조 게이트
Phase 2.5(공통)와 동일 — verify gates.py genre {genre} . Bash 1회 — LLM 콜 아님.
Phase P3: finalize (heavy는 항상)
humanize finalizer 를 Agent 도구로 1회 호출.
입력: original path=01 input.txt , rewritten path=final.md , diagnosis path=02 diagnosis.md
원문↔윤문본 직접 대조 로 의미 보존 15항(각주·제목·없던 주장 주입 포함) + 자연성(잔존 + 과윤문 양방향)을 판정하고 문제 구간만 국소 보정 (전체 재작성 금지).
출력: 보정된 final.md (원본은 final pre finalize.md 백업) + 09 finalize.json .
verdict=hold and report 면 사람 검토 안내. 그 외 finalize 후 verify gates.py 를 한 번 더 돌려 최종 변경률 확정.
콜 수: 3 (진단 1 + 윤문 1 + finalize 1). 청크 병렬 시 2 + N + 국소 패치.
Finalize 승급 규칙 (전 경로 공통)
finalize는 추가 LLM 콜이다. 다음 조건에서만 실행한다:
조건 finalize
heavy 경로 항상
변경률 게이트 exit 1(경고 30~50%) 실행 — 과윤문·의미 드리프트 의심
monolith 자체검증 실패(6항 중 2+ 위반) 실행
사용자가 검증·증적을 명시 요청 실행
light·standard의 그 외 모든 경우 생략 — verify gates.py 결정적 게이트가 과윤문을 확인
진단 파일이 없을 때(Light 승급). Light 경로는 02 diagnosis.md 를 만들지 않는다. Light에서 승급 조건에 걸리면 diagnosis path 없이 humanize finalizer 를 호출한다 — 진단을 만들려고 콜을 추가하지 않는다. finalize의 본체(의미 보존 15항 + 자연성)는 원문↔윤문본 직접 대조로 성립하므로 진단 없이도 온전히 동작하며, 이 경우 도구 호출은 3회로 줄어든다. (Light가 승급하는 상황은 애초에 "예상보다 많이 고쳤다"이므로, 겨냥 대상을 새로 진단하는 것보다 고친 결과를 검증하는 것이 맞다.)
Phase 2.4: 서법 국소 복원 (전 경로 공통, 게이트 직전 )
P5는 서법 위반을 판정만 한다. 판정 전에 고칠 수 있는 것은 고쳐 둔다 — 유보·요구가
사라진 문장만 원문 문장으로 되돌리는 결정적 변형이다. LLM 콜 0회.
두 번째 명령은 C 11 역주입 제거 — 윤문이 새로 쓴 문장에서만 연결어미 뒤
쉼표를 걷어낸다(원문에 있던 문장은 불가침 — 필자 쉼표 보호). light 실측에서
윤문 후 연결어미 쉼표가 원문보다 늘어난 문서가 16/28이었다. LLM 콜 0회.
all 격상 (standard·heavy 한정) : 02 diagnosis.md 가 C 11(연결어미 뒤
쉼표)을 탐지 티로 지목한 경우에만 두 번째 명령에 all 을 붙인다 — 전 문장
(따옴표 안 제외)에서 제거해 원문에 실려 온 주입 쉼표(잔존분)까지 걷어낸다.
근거: 사람 532편 실측에서 연결어미 쉼표는 사람 중앙값이 문장의 15%라
밀도만으로는 사람/주입을 못 가른다 — 그래서 격상 조건은 밀도 임계가
아니라 경로+진단 판정이다. 진단이 없는 light 경로에서는 절대 쓰지 않는다.
왜 필요한가 : 규칙(A 10·G 1)을 보존 쪽으로 고쳐도 프롬프트는 확률적이라 계속 샌다.
스킬을 실제로 돌린 A/B에서 규칙 양쪽 버전 모두 "낮은 것으로 판단된다" → "낮은 수치다"
변환이 남았다. 복원기를 붙이면 그 문장만 되돌아온다.
왜 게이트 직전인가 : 순서가 뒤바뀌면 게이트가 먼저 WARN을 띄우고 실행자가 윤문본을
통째로 롤백한다. 문장 단위로 되돌린 뒤 판정해야 서법은 지키면서 나머지 윤문이 산다.
되돌린 문장의 AI 티도 함께 돌아온다. 의미 보존이 티 제거보다 우선한다는 정책에 따른
트레이드오프다. 복원 건수는 결과 전달의 summary 블록에 적는다.
애매하면 손대지 않고 보고만 한다(보류) — 짝 문장 유사도가 낮거나, 치환 대상이 결과에서
유일하지 않거나, 문장 병합이 의심될 때. 보류 건은 게이트가 P5로 잡는다.
Phase 2.5: 구조 게이트 (철칙 4 — 결정적 검증, 전 경로 공통)
monolith가 자체 보고한 변경률은 참고값 이다. 철칙 4의 게이트 판정은 코드가 한다.
문자 기반 변경률은 구조 편집에 눈이 없다(실측: change rate 2.77% 뒤에 문장 터치율 29.7%·대구 75%가 은닉). verify gates.py 는 문자율에 목표 달성·대구 전멸·golden+수치 3축을 더해 이 사각지대를 보완한다.
윤문본이 나온 직후 Bash로 1회 실행:
exit code로 분기한다 (0/1/2/3 의미는 기존 게이트와 동일):
exit 판정 후속
0 수렴 — 4축 모두 통과 결과 전달 진행
1 경고 — 문자율 30~50% / S1 목표 미달·과교정 / 대구 전멸 / golden FAIL 결과 전달 + 해당 축 고지 + finalize 승급
2 중단 — 문자율 ≥ 50% 윤문본 채택 금지. monolith에 롤백 지시 후 1회 재실행, 재차 2면 hold and report
3 판정 불가 입력 파일 확인 후 재시도. 게이트를 건너뛰지 않는다
스크립트가 <! HUMANIZE SUMMARY 블록을 자동 제거하고 비교하므로 별도 전처리 불필요.
헤딩·불릿 산문화가 많아 변경률이 부풀려진 것으로 보이면 ignore markup 으로 본문만 재측정해 교차 확인한다. 판정을 뒤집는 근거로 쓰려면 두 수치를 모두 사용자에게 보고할 것.
이 수치가 SSOT다. 결과 전달의 상태 줄과 summary 블록에는 스크립트 출력값을 쓴다. 에이전트 자가 산출값으로 덮어쓰지 않는다.
결과 전달 (전 경로 공통)
사용자에게 다음 4개를 반환:
1. 한 줄 상태: 완료. 경로 {light standard heavy} / 변경률 X% / 등급 Y / 자체검증 N/6 통과 — 변경률은 게이트 스크립트 출력값 을 그대로 쓴다
2. 윤문본 본문 (마크다운 블록) — 단, light 조기 종료면 "이미 좋습니다 + 손댄 곳 요약"으로 대체 가능
3. final.md 끝 <! HUMANIZE SUMMARY 블록의 핵심 표 (메트릭 + 카테고리 탐지 + 자체검증)
4. 등급 B 이하면 "heavy( strict , 진단→윤문→finalize 3콜)로 재실행" 안내
wall clock 목표: light 1~2분 / standard 5,000자 2~3분·1만자 3~5분(단일 콜) / heavy 5~8분.
부분 재실행 / 후속 명령
사용자 신호 처리
"특정 카테고리만 다시" heavy 경로. 02 diagnosis.md 의 지배 패턴을 해당 카테고리로 한정해 P1부터 재실행
"이 문단만" heavy 경로, 해당 문단만 입력으로 새 run id 생성
"2차 윤문"·" /humanize redo " 기존 run id의 final.md 를 새 입력으로 heavy P1부터 재실행
"윤문 강도 조정" heavy 경로, 진단의 지배 패턴 개수(3~6)를 늘리거나 줄여 재실행
"장르 바꿔서" genre 변경 후 Phase 1부터 재실행 (경로는 route hint 재판정)
옵션 (인자 끝에 자연어로)
장르: 칼럼 리포트 블로그 공적 — 장르 명시 (생략 시 자동 추정)
강도: 보수 기본 적극 — 윤문 강도 (기본값: 기본. light 경로는 항상 보수)
strict / 정밀 모드 — heavy 경로 강제 (route hint 무시)
가볍게 / 빠르게만 — light 경로 강제
데이터 흐름 요약
설계 노트 (요약 — 전문은 design notes.md)
단일 콜 우선 — 근거: 1만자 실측에서 청킹 7콜 610K 토큰 vs 단일 콜 134K, 품질 동등(폭발 원인 = 청크마다 룰북·진단 재로드). 청킹 확대는 이 사고의 재현이다.
route hint 분기 — 근거: 잘 쓴 글에도 최중량 파이프라인을 돌리던 낭비를 차단.
3콜 구조 — 근거: 옛 5인 파이프라인은 span 열거 0↔18 요동 + taxonomy 이중 로드로 wall clock 54%를 탐지에 소모.
경로 LLM 콜 수 대상 비고
light 1 (게이트 실패 시 2) 잘 쓴 글 — 어휘 티 0·구조 티 미미 진단·finalize 생략, 보수 강도
standard 2 (승급 시 3) 보통의 AI 초안 진단 + 단일 윤문. 1만자도 단일 콜
heavy 3 (청킹 시 2+N+1) 중증 슬롭·초장문·증적 필요 완전한 진단→윤문→finalize
에이전트 호출 규칙
모델: 런타임 3종 모두 model: opus . (모델 선택은 본 스킬의 관할이 아니다 — 오픈소스 사용자가 정한다. v2.2의 절감은 전적으로 콜 수·경로에서 온다.)
에이전트 정의 위치: 저장소 루트 agents/ 에 9종 정의(플러그인 컨벤션). Claude Code 탐색 경로:
1. 플러그인 설치 시 — humanize korean 플러그인이 agents/ 를 번들로 제공(전역).
2. 스크립트 설치 시 — install.sh 가 agents/ .md 를 ~/.claude/agents/ 에 심링크(전역).
9종의 내역은 런타임 3 + 유지보수 1 + 개발용 1회성 5이며,