Content & Writing

Humanize Korean

humanize-korean

Rewrite Korean text that reads as AI-written — translationese, over-quoted English, mechanical parallelism, passive overuse, uniform rhythm, emoji and bullet excess — across 10 categories of tells, changing style and rhythm without touching the content. Routes to 1, 2 or 3+ passes by severity.

koreaneditingtranslationesehumanize
Install
mkdir -p ~/.claude/skills && curl -fsSL https://skill.metacog.co.kr/dist/humanize-korean.zip \
  -o /tmp/humanize-korean.zip && unzip -oq /tmp/humanize-korean.zip -d ~/.claude/skills
Files16
Size333.1 KB
Bundled foldersreferences/
LicenseMIT

This skill produces Korean-language output by default.

Redistributed from epoko77-ai/im-not-ai (MIT) · Browse files on GitHub · Download zip

When Claude uses it

AI(ChatGPT·Claude·Gemini 등)가 쓴 한글 텍스트를 "사람이 쓴 글처럼" 윤문해주는 오케스트레이터 스킬. 번역투·영어 인용 과다·기계적 병렬·관용구·피동태 남용·접속사 남발·리듬 균일성·이모지/불릿 과다 등 10대 카테고리 70개 AI 티 패턴을 탐지·분류해 내용은 한 글자도 건드리지 않고 문체·리듬·표현만 자연스러운 한국어로 재작성한다. shim의 route_hint(light|standard|heavy)로 경로를 정해 잘 쓴 글은 1콜, 표준은 2콜, 중증·장문만 3+콜(진단→겨냥 윤문→finalize)로 처리한다. 트리거 — "AI 티 없애줘", "AI 같은 글 자연스럽게", "GPT/ChatGPT 문체", "AI 번역투 고쳐", "사람이 쓴 것처럼 윤문", "AI 윤문", "ChatGPT 티 제거", "한글 AI 탐지·윤문", "AI 글 사람처럼", "번역투 제거", "영어 인용 많은 글 윤문", "AI 글 티 안 나게", "휴머나이저", "humanize Korean", "AI detector bypass 한글". 후속 작업 — "특정 카테고리만 다시", "윤문 강도 조정", "장르 바꿔서", "이 문단만", "2차 윤문" 도 모두 이 스킬. 단순 맞춤법·오탈자 교정은 직접 처리, 번역은 번역 스킬, 내용 추가·삭제를 동반한 재작성은 별도 집필 스킬.

SKILL.md

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

Phase 0: 컨텍스트 확인 및 경로 결정

작업 시작 시 가장 먼저 다음 한 줄을 사용자에게 출력한다.

humanize-korean v2.3 — 경로: {light|standard|heavy} ({route_hint|사용자 지정}) / run_id: {YYYY-MM-DD-NNN}

(경로는 Phase 1의 shim 실행 후에 확정되므로, 이 상태 줄은 shim 직후 출력한다.)

전 경로 공통 의미 앵커

경로 결정 규칙

  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 결정

올바른 사용법: Glob(pattern="_workspace/YYYY-MM-DD-*/01_input.txt") → 결과에서 폴더명 추출 후 NNN 최댓값 + 1. 주의: Glob은 디렉토리 자체는 매칭하지 못한다. 반드시 그 안의 표지 파일(01_input.txt)을 매칭할 것. Bash ls는 OS·셸 환경에 따라 경로 해석이 달라지므로 사용 금지.

스크립트 경로 규칙 (${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 시작 전에 한 번 정한다.

SKILL_ROOT="$(d="$(cd -P "${CLAUDE_SKILL_DIR}" && pwd)"; \
  while [ "$d" != / ] && [ ! -d "$d/.claude-plugin" ]; do d="$(dirname "$d")"; done; echo "$d")"

.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에 저장
  1. 첫 300자로 장르 자동 추정 (사용자 명시 시 우선)
  2. 사전 처리 shim을 Bash로 1회 실행:

`` python3 ${SKILL_ROOT}/scripts/prepare_monolith_input.py --run-dir _workspace/{run_id} --genre {genre} ``

  1. 00_metrics.json의 route_hint를 읽어 Phase 0 규칙대로 경로를 확정하고 상태 줄을 출력한다.

단일 콜 우선 — 청킹은 여기서 하지 않는다. --chunk는 heavy 경로 전용이며, 그때도 청크 경로를 탈지는 shim이 실제로 청크를 2개 이상 만들었는지로 정한다(heavy 절 참조).

Light 경로 (1콜) — 잘 쓴 글

어휘 티가 거의 없고 구조 티만 미미한 글. 목표는 과윤문 방지이지 많이 고치는 게 아니다.

  1. 진단 생략. humanize-monolith를 Agent 도구로 1회 호출 — 청킹 없음.
  1. Phase 2.5 변경률 게이트(Bash — LLM 콜 아님).
  2. 조기 종료 보고: monolith 탐지가 거의 없고 게이트 변경률이 5% 미만이면, 결과 전달을 "이미 좋은 글입니다 — 손댄 곳은 {N}곳({요지}) 정도"로 요약한다. 억지로 더 고치지 않는다.
  3. 게이트 exit 2(≥50%)일 때만 롤백 재실행 1회(이 경우 총 2콜). light에서 50%가 나오면 과윤문 사고이므로 재실행 지시에 보수 강도를 재강조한다.

콜 수: 1 (게이트 실패 시 최대 2).

Standard 경로 (2콜) — 보통의 AI 초안

  1. 진단 1콜: humanize-diagnostician을 Agent 도구로 1회 호출.
  1. shim으로 진단을 monolith 입력 앞에 결합 (Bash — LLM 콜 아님):

`` python3 ${SKILL_ROOT}/scripts/prepare_monolith_input.py --run-dir _workspace/{run_id} --genre {genre} --diagnosis _workspace/{run_id}/02_diagnosis.md ` → 01_input_with_metrics.txt`가 [진단 → 정량 블록 → 원문] 순으로 재생성된다.

  1. 윤문 1콜: humanize-monolith 1회 호출 — 청킹 없음. 1만자급도 단일 콜이다. → final.md.
  2. Phase 2.5 변경률 게이트(Bash).
  3. 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를 함께 줄 수 있다:

`` python3 ${SKILL_ROOT}/scripts/prepare_monolith_input.py --run-dir _workspace/{run_id} --genre {genre} --diagnosis _workspace/{run_id}/02_diagnosis.md --chunk ``

  1. 청크 경로 판정: chunk_manifest.json의 body 청크(passthrough 제외)가 2개 이상일 때만 청크 경로. 1개면 단일 monolith 콜로 처리한다 — 청킹은 shim의 결정이지 오케스트레이터의 추측이 아니다. 단일 콜로 처리할 때의 입력 파일도 manifest가 있으면 그 청크의 input_file 값을, 없으면 01_input_with_metrics.txt를 쓴다.
  2. 단일 콜(기본): humanize-monolith 1회 호출(input_path=01_input_with_metrics.txt). monolith는 진단문을 앞머리에서 읽고 지배 패턴을 겨냥해 윤문한다. → final.md.
  3. 청크 병렬(shim이 실제로 쪼갠 경우만):

Phase P2.5: 구조 게이트

Phase 2.5(공통)와 동일 — verify_gates.py --genre {genre}. Bash 1회 — LLM 콜 아님.

Phase P3: finalize (heavy는 항상)

humanize-finalizer를 Agent 도구로 1회 호출.

콜 수: 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회.

python3 ${SKILL_ROOT}/scripts/restore_modality.py \
    --before _workspace/{run_id}/01_input.txt \
    --after  _workspace/{run_id}/final.md \
    --out    _workspace/{run_id}/final.md
python3 ${SKILL_ROOT}/scripts/strip_injected_commas.py \
    --before _workspace/{run_id}/01_input.txt \
    --after  _workspace/{run_id}/final.md \
    --out    _workspace/{run_id}/final.md

두 번째 명령은 C-11 역주입 제거 — 윤문이 새로 쓴 문장에서만 연결어미 뒤 쉼표를 걷어낸다(원문에 있던 문장은 불가침 — 필자 쉼표 보호). light 실측에서 윤문 후 연결어미 쉼표가 원문보다 늘어난 문서가 16/28이었다. LLM 콜 0회.

--all 격상 (standard·heavy 한정): 02_diagnosis.md가 C-11(연결어미 뒤 쉼표)을 탐지 티로 지목한 경우에만 두 번째 명령에 --all을 붙인다 — 전 문장 (따옴표 안 제외)에서 제거해 원문에 실려 온 주입 쉼표(잔존분)까지 걷어낸다. 근거: 사람 532편 실측에서 연결어미 쉼표는 사람 중앙값이 문장의 15%라 밀도만으로는 사람/주입을 못 가른다 — 그래서 격상 조건은 밀도 임계가 아니라 경로+진단 판정이다. 진단이 없는 light 경로에서는 절대 쓰지 않는다.

스킬을 실제로 돌린 A/B에서 규칙 양쪽 버전 모두 "낮은 것으로 판단된다" → "낮은 수치다" 변환이 남았다. 복원기를 붙이면 그 문장만 되돌아온다.

통째로 롤백한다. 문장 단위로 되돌린 뒤 판정해야 서법은 지키면서 나머지 윤문이 산다.

트레이드오프다. 복원 건수는 결과 전달의 summary 블록에 적는다.

유일하지 않거나, 문장 병합이 의심될 때. 보류 건은 게이트가 P5로 잡는다.

Phase 2.5: 구조 게이트 (철칙 #4 — 결정적 검증, 전 경로 공통)

monolith가 자체 보고한 변경률은 참고값이다. 철칙 #4의 게이트 판정은 코드가 한다. 문자 기반 변경률은 구조 편집에 눈이 없다(실측: change_rate 2.77% 뒤에 문장 터치율 29.7%·대구 -75%가 은닉). verify_gates.py는 문자율에 목표 달성·대구 전멸·golden+수치 3축을 더해 이 사각지대를 보완한다. 윤문본이 나온 직후 Bash로 1회 실행:

python3 ${SKILL_ROOT}/scripts/verify_gates.py \
    --before _workspace/{run_id}/01_input.txt \
    --after  _workspace/{run_id}/final.md \
    --genre {genre}

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 | 판정 불가 | 입력 파일 확인 후 재시도. 게이트를 건너뛰지 않는다 |

결과 전달 (전 경로 공통)

사용자에게 다음 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 재판정) |

옵션 (인자 끝에 자연어로)

데이터 흐름 요약

01_input.txt
    ↓ [scripts/prepare_monolith_input.py — 정량 점수 shim, Bash 1회]
00_metrics.json (route_hint 포함) + 01_input_with_metrics.txt
    ↓ route_hint (사용자 명시가 오버라이드)
    ├─ light ──→ [humanize-monolith ×1, 보수] ──→ final.md ──→ [verify_gates.py]
    │             (변경률 <5%면 "이미 좋습니다" 조기 종료 보고)
    ├─ standard → [humanize-diagnostician ×1] → 02_diagnosis.md
    │             ↓ [shim --diagnosis, Bash]
    │             [humanize-monolith ×1 — 단일 콜, 1만자급 포함] → final.md
    │             ↓ [verify_gates.py] (finalize는 승급 조건 시만)
    └─ heavy ───→ [humanize-diagnostician ×1] → 02_diagnosis.md
                  ↓ [shim --diagnosis (--chunk 가능), Bash]
                  [humanize-monolith ×1 — 또는 shim이 2+청크를 쪼갠 경우만 병렬 ×N]
                  ↓ [verify_gates.py]
                  [humanize-finalizer ×1] → final.md(보정) + 09_finalize.json
                  ↓ [verify_gates.py — 최종 확정]

설계 노트 (요약 — 전문은 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이며, 본 스킬 런타임이 호출하는 것은 3종뿐이다.

런타임 3종 (스킬 실행 중 호출)

유지보수 1종 (별도 명령으로만 트리거)

(개발용 1회성 5종·v2.1 은퇴 5종의 계보와 테스트 시나리오는 ${CLAUDE_SKILL_DIR}/references/design-notes.md 참조.)

주의 사항

참고 자료