
Humanize Korean
- 168 installs
- 4.1k repo stars
- Updated July 22, 2026
- epoko77-ai/im-not-ai
Remove AI patterns from Korean text using 40+ pattern detectors for translation-speak and mechanical phrasing.
About
Humanize Korean removes AI-generated Korean writing patterns using 40+ detectors for translation effects and mechanical phrasing. Preserves meaning while naturalizing Korean prose.
- 40+ Korean-specific AI pattern detectors.
- Strict mode with parallel verification agents.
Humanize Korean by the numbers
- 168 all-time installs (skills.sh)
- Ranked #625 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/epoko77-ai/im-not-ai --skill humanize-koreanAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 168 |
|---|---|
| repo stars | ★ 4.1k |
| Last updated | July 22, 2026 |
| Repository | epoko77-ai/im-not-ai ↗ |
What it does
Remove AI patterns from Korean text using 40+ pattern detectors for translation-speak and mechanical phrasing.
Files
Humanize Korean — AI 한글 티 제거 오케스트레이터 (v1.5)
v1.5 변경 고지 (2026-04-26) — v1.1 베이스라인 + Monolith Fast Path
v1.2(voice profile)·v1.3(candidate pool)·v1.4(역할별 모델 분산)는 모두 핫패스 비용을 잡지 못해 5,000자 입력에 25분이 걸렸습니다. v1.5는 v1.1 단순 구조로 롤백한 뒤 단일 호출 monolith 에이전트만 추가한 설계입니다.
>
- Fast 모드(디폴트) — humanize-monolith 에이전트가 한 콜에서 탐지·윤문·자체검증 일괄 처리. 도구 호출 4~5회. 5,000자 이하 wall-clock 2~3분 목표.- Strict 모드(`--strict`) — v1.1 5인 파이프라인 그대로(detector·rewriter·auditor·reviewer + taxonomist 분류 자산 유지). 정밀 검증·장문(8,000자+) 처리·etc.
- 삭제됨: voice profile·candidate pool·promotion-checklist·sample-collection·권한 위계 §1~§6.
- 유지됨: 분류 체계 본진(C-9·C-10·D-7·H-3·I-3·I-4 등 v1.2~v1.3.1 신규 패턴)·rewriting-playbook·5인 에이전트 정의(strict 모드 백본).
Phase 0: 컨텍스트 확인 및 모드 결정
작업 시작 시 가장 먼저 다음 한 줄을 사용자에게 출력한다.
humanize-korean v1.5 — {fast|strict} 모드 / run_id: {YYYY-MM-DD-NNN}모드 결정
- 사용자가
--strict·"정밀 모드"·"5인 파이프라인" 명시 → strict - 입력 8,000자 초과 → strict (자동 승급 + 사용자에 1줄 고지)
- 그 외 모두 → fast (디폴트)
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 재사용 + strict 모드로 자동 승급.
Fast 모드 (디폴트)
Phase 1: 입력 저장
1. cwd 기준 _workspace/{run_id}/ 생성 2. 입력 텍스트를 01_input.txt에 저장 3. 첫 300자로 장르 자동 추정 (사용자 명시 시 우선)
Phase 2: Monolith 호출
humanize-monolith 에이전트를 Agent 도구로 1회 호출.
입력:
input_path: <abs path>/_workspace/{run_id}/01_input.txt
quick_rules_path: ${CLAUDE_SKILL_DIR}/references/quick-rules.md
genre_hint: 칼럼 | 리포트 | 블로그 | 공적 | null출력 (에이전트가 직접 작성):
_workspace/{run_id}/final.md— 윤문본_workspace/{run_id}/summary.md— 메트릭·자체검증·하이라이트
monolith는 단일 호출 안에서 다음을 모두 수행 (자세히는 에이전트 정의 참조): 1. quick-rules 룰북 로드 → 메모리에서 패턴 탐지 + 윤문 + 자체검증 6항 점검 2. 변경률 50% 초과 시 자동 롤백 3. 자체검증 위반 시 1회 부분 재실행 4. final.md + summary.md 작성
Phase 3: 결과 전달
사용자에게 다음 4개를 반환: 1. 한 줄 상태: 완료. 변경률 X% / 등급 Y / 자체검증 N/6 통과 2. 윤문본 본문 (마크다운 블록) 3. summary.md의 핵심 표 (메트릭 + 카테고리 탐지 + 자체검증) 4. 등급 B 이하면 "정밀 검증이 필요하면 --strict로 5인 파이프라인" 안내
디폴트 wall-clock 목표: 5,000자 이하 2~3분, 8,000자 5~7분.
Strict 모드 (--strict 또는 자동 승급)
v1.1 5인 파이프라인 그대로. 검증 분리·재윤문 루프가 의미 있을 때만 사용.
Phase A: 탐지
ai-tell-detector 호출 → 02_detection.json
Phase B: 윤문 (최대 3회 루프)
korean-style-rewriter 호출 → 03_rewrite.md + 03_rewrite_diff.json
Phase C: 병렬 검증 (에이전트 팀)
TeamCreate로 humanize-review-team 구성:
content-fidelity-auditor→04_fidelity_audit.json(의미 동등성)naturalness-reviewer→05_naturalness_review.json(잔존·과윤문)
TeamDelete 후 종합 판정 매트릭스에 따라 분기:
| fidelity | naturalness | 종합 | 후속 |
|---|---|---|---|
| full_pass | accept / accept_with_note | 최종 승인 | Phase D |
| full_pass | rewrite_round_2 | 2차 윤문 | Phase B 재호출 (target finding) |
| full_pass | rollback_and_rewrite | 롤백 후 재윤문 | 윤문가에 edit 롤백 지시 |
| conditional_pass | - | 롤백된 edit만 재시도 | Phase B 재호출 |
| fail | - | 전면 재작업 | Phase B 전면 재호출 |
2차/3차 윤문 진입 시 03_rewrite_v2.md·v3.md로 버전 분리. 최대 3회 후 미해결이면 `hold_and_report`로 사람 개입.
Phase D: 최종 출력
1. final.md에 최종 윤문본 복사 2. summary.md 생성 (fast 모드와 동일 포맷) 3. 사용자에게 결과 + 등급 + 안내
부분 재실행 / 후속 명령
| 사용자 신호 | 처리 |
|---|---|
| "특정 카테고리만 다시" | strict 모드로 자동 전환, 해당 카테고리 finding만 Phase B 재실행 |
| "이 문단만" | strict 모드, 해당 문단만 입력으로 새 run_id 생성 |
"2차 윤문"·"/humanize-redo" | 기존 run_id의 final.md를 새 입력으로 strict Phase B 재실행 |
| "윤문 강도 조정" | strict 모드, min_severity 옵션 변경 후 Phase A부터 재실행 |
| "장르 바꿔서" | genre_hint 변경 후 Phase A부터 재실행 |
옵션 (인자 끝에 자연어로)
장르: 칼럼|리포트|블로그|공적— 장르 명시 (생략 시 자동 추정)강도: 보수|기본|적극— 윤문 강도 (기본값: 기본)최소심각도: S1|S2|S3— 탐지 임계값 (기본값: S2)--strict— 5인 파이프라인 강제 사용
데이터 흐름 요약
Fast 모드 (디폴트)
01_input.txt
↓ [humanize-monolith — 단일 호출]
├ 메모리: quick-rules 로드 → 탐지 → 윤문 → 자체검증
└→ final.md + summary.mdStrict 모드
01_input.txt
↓ [ai-tell-detector]
02_detection.json
↓ [korean-style-rewriter]
03_rewrite.md + 03_rewrite_diff.json
↓ [병렬 팀]
├→ [content-fidelity-auditor] → 04_fidelity_audit.json
└→ [naturalness-reviewer] → 05_naturalness_review.json
↓ [오케스트레이터 종합]
├→ (재작업) Phase B로 복귀 (최대 3회)
└→ (승인) final.md + summary.md에이전트 호출 규칙
모델: 모두 model: opus 통일 (v1.1 베이스라인). 모델 다운그레이드는 v1.4에서 시도했으나 도구 호출 chain이 진짜 병목이라 효과 미미했음.
에이전트 정의 위치: 저장소 루트 agents/에 12종 정의(플러그인 컨벤션). Claude Code 탐색 경로: 1. 플러그인 설치 시 — humanize-korean 플러그인이 agents/를 번들로 제공(전역). 2. 스크립트 설치 시 — install.sh가 agents/*.md를 ~/.claude/agents/에 심링크(전역).
필요 에이전트 6종:
humanize-monolith(v1.5 신규, fast 전용)ai-tell-detector·korean-style-rewriter·content-fidelity-auditor·naturalness-reviewer(strict 5인 중 4명)korean-ai-tell-taxonomist(분류 체계 유지·확장 — 본 스킬 실행 중에는 호출 안 됨, 별도 명령으로만 트리거)
테스트 시나리오
Fast 정상 흐름
- 입력: ChatGPT가 생성한 AI 칼럼 초안 (2,000~5,000자, 번역투·결말 공식·hype 어휘 풍부)
- 기대: monolith 1콜로 변경률 15~25%, 등급 A/B, wall-clock 2~3분, 자체검증 5~6/6
Strict 정밀 검증 흐름
- 사용자 명시
--strict또는 8,000자+ 입력 - 5인 파이프라인 끝까지 실행, 변경률 18~22%, 검증팀 full_pass
엣지 케이스 — 이미 사람이 쓴 글
- monolith 자체 탐지에서 매치 거의 없음 → 변경률 5% 미만 + summary.md에 "윤문 불필요 가능성" 메모
- 사용자가
--strict로 강제 검증 가능
주의 사항
- 의미 불변이 최상위 불문율. monolith·strict 모두에서 위반 즉시 롤백.
- 수치·고유명사·직접 인용은 탐지/윤문 대상 아님. Do-NOT list 엄수.
- 장르 이탈 금지. 칼럼이 에세이로, 에세이가 문학으로 옮겨가지 않는다.
- register 보존. 격식체 입력 → 격식체 출력. AI 티는 문법·수사이지 격식 자체가 아님.
- 변경률 30% 초과 → 경고, 50% 초과 → 강제 중단.
- 자동 로드 금지. 프로젝트 CLAUDE.md 등 다른 파일을 자동 파싱해 옵션을 추론하지 않는다.
참고 자료
- 슬림 룰북 (Fast 전용): `references/quick-rules.md` — S1·S2 핵심 패턴 + 자체검증 체크리스트
- 분류 체계 본진 (Strict 전용): `references/ai-tell-taxonomy.md` — 10대분류 × 40+ 패턴 전수
- 윤문 처방 (Strict 전용): `references/rewriting-playbook.md` — 카테고리별 치환 레시피·장르별 허용 표
- 웹 서비스 스펙 (옵션): `references/web-service-spec.md` — 웹 확장 시 로드
AI 한글 티 분류 체계 v2.0 (Korean AI-Tell Taxonomy)
LLM(ChatGPT·Claude·Gemini 등)이 생성한 한글 글에서 반복적으로 관찰되는 "AI 티" 패턴을 10개 대분류 × 서브 패턴으로 정리한다. 탐지기·윤문가·리뷰어가 공유하는 단일 진실 원천(SSOT). 각 패턴마다 (1) 정의, (2) 시그니처 예문, (3) 심각도(S1 결정적 / S2 강함 / S3 약함), (4) 윤문 처방을 제공한다.
v2.0 추가 (2026-05-07): 한국 번역학계 8대 번역투 정통성 계보(이영옥 2001·김도훈 2009·김정우 2007·김혜영 2019 등) + 보고서 §III.3(8유형) 통합. 본진 신규 4건 —A-16영어 대명사 직역 [S1] ·A-18관계절 좌향 수식 [S2] ·A-19이중 조사 결합 [S2] ·E-7청자 경어법 일관성 손실 [S2 · estimated]. 본진 보강 4건 —A-15인지·발화 동사 분리 구문 처방 ·A-7light verb construction 일반화(have/make/take/give) ·F-4영어 명사화 접미사(-tion·-ment·-ness·-ity) 통합 ·E-2진행형 '~고 있다' 자동 매핑 처방. 본진 hold 1건 —A-17무정물·추상명사 '-들' 부착 [학술 강함, 외부 회차 양성 0건 → NMT 원본 회차 후 v2.1 재평가]. post-editese 3축은 metric-only 트랙 — caveat C3(한국어 정량 검증 부재)에 따라 본진 ID 미부여,metrics_v2.py14개 신규 함수로 운영(deul_overuse_rate포함, A-17 hold 검증용). 학술 전문은 외부 SSOTreferences/scholarship.md에 보존(본진 슬림성). valid as of 2026-05.
>
v1.6 추가 (2026-05-06): KatFish(Park et al.) + LREAD 외부 정량 연구 기반 본진 신규 5건 —C-11연결어미 뒤 쉼표 [S1, 4.84배 분리도] ·C-12쉼표 포함률 [S2] ·E-5쉼표 분절 평균 길이 [S2] ·E-6쉼표 전후 POS 다양성 [S2, 에세이·뉴스 한정] ·G-3안전 균형 lexicon [S2]. 본진 보강 2건 —D-1에 KatFish 검증 결산 lexicon 4종("결론적으로·따라서·이를 통해·그러므로") 정식 인용 + 임계,F-4에 한자어 명사화 접미사 3종("-성·-적·-화") 정식 명시 + 한 문서 12회 초과 임계. hold 2건(BN/VX 띄어쓰기 규칙성·페르소나-레지스터 불일치)은 본진 미등재 —_workspace/v1.6-2026-05-06/에 후보 발자취 보존.
>
v1.5.1 추가 (2026-04-27): Category E에 E-4 단문 일변도 (복문·중문 부재) [S2] 신설. 인간 필자는 단문과 복문을 무의식적으로 섞어 호흡을 만드는데, AI가 "간결하게" 의도하면 단문만 늘어놓아 끊어진 리듬이 그 자체로 시그니처가 된다.>
v1.5 변경 (2026-04-26): v1.2 voice profile · v1.3 candidate pool · v1.3.1 권한 위계는 모두 제거됐다. 이유는 핫패스 비용. v1.5는 v1.1 5인 파이프라인 구조 + monolith fast 1콜로 단순화됐고, 분류 체계 본진(이 파일)은 v1.3.1까지 발굴된 신규 패턴(C-9·C-10·D-7·H-3·I-3·I-4 보강 등)을 그대로 유지한다.
심각도 기준
- S1 결정적(critical): 한 번만 나와도 "이건 AI"라고 거의 확신하게 되는 패턴. 무조건 제거.
- S2 강함(high): 1~2회는 자연스러울 수 있으나 문서에서 3회 이상 반복되면 티 남. 밀도 기반 제거.
- S3 약함(low): 개별로는 문제 아님. 다른 패턴과 중첩될 때 AI 인상을 강화. 리듬 조정 수준.
목차
A. 번역투(Translation-ese) — A-1~A-19 B. 영어 인용·용어 과다 — B-1~B-4 C. 구조적 AI 패턴 (서식·레이아웃) — C-1~C-12 D. AI 특유의 관용구 (Signature Phrases) — D-1~D-7 E. 리듬·문장 길이 균일성 — E-1~E-7 F. 과도한 수식·중복 — F-1~F-5 G. 과도한 Hedging (완곡) — G-1~G-3 H. 접속사 남발 — H-1~H-4 I. 형식명사·의존명사 과다 — I-1~I-6 J. 시각 장식 남용 — J-1~J-4
---
A. 번역투 (Translation-ese) — S1~S2
영어·일본어식 구문을 한국어 어순·조사 체계로 무리하게 옮긴 흔적. AI 글의 가장 결정적 시그니처.
A-1. "~에 대하여/대해서" 남발 [S1]
- 패턴:
X에 대해(서) Y(영어about/regarding X) - 예: "AI 규제에 대해 논의할 필요가 있다" → "AI 규제를 논의해야 한다"
- 처방: 목적격 조사로 직결. 또는 주제 조사 "는".
A-2. "~를 통하여/통해" 남발 [S1]
- 패턴: 수단·경로를 거의 모두 "통해"로 처리 (영어
through/via) - 예: "데이터 분석을 통해 인사이트를 얻는다" → "데이터를 분석해 인사이트를 얻는다"
- 처방: "~로", "~해서", "~함으로써" 등으로 분산.
A-3. "~에 있어(서)" [S1]
- 패턴: 전제·상황 도입 (영어
in terms of / when it comes to) - 예: "이 문제에 있어서 중요한 것은" → "이 문제에서 중요한 것은" / "이 문제를 볼 때"
A-4. "~라는 점에서" [S2]
- 패턴: 근거 제시 (영어
in the sense that) - 예: "확장성이 뛰어나다는 점에서 의미가 있다" → "확장성이 뛰어나서 의미가 있다"
- 주의: 때로는 자연스러움. 한 문서에 3회+ 반복될 때만 제거.
A-5. "~와 관련하여" / "~와 관련된" [S2]
- 패턴: 주제 지시 (영어
regarding / related to) - 예: "보안과 관련하여 주의해야 한다" → "보안에 주의해야 한다"
A-6. "~에 기반하여" / "~을 바탕으로" 남발 [S2]
- 패턴: 근거 (영어
based on) - 예: "데이터에 기반하여 판단한다" → "데이터로 판단한다" / "데이터를 보고 판단한다"
A-7. "가지고 있다" [S1]
- 패턴: 소유·특성 서술 (영어
have/possess) - 예: "강한 경쟁력을 가지고 있다" → "경쟁력이 강하다"
- 처방: 형용사형으로 돌려 서술어 없애거나 "있다"로 단순화.
- light verb construction 일반화 (v2.0 보강): 보고서 T6은 'have/make/take/give + 명사' 가벼운 동사 구문(light verb construction) 전반을 다룸. A-7 본진 처방 위에 (a) 동사 환원, (b) 이중주어 구문('X는 Y가 …') 활용을 명시 추가. verbatim 예문 — "She has a sweet voice → 그녀는 목소리가 아름답다" / "She has a book under her arm → 그녀는 책을 옆구리에 끼고 있다" / "We had a meeting yesterday → 우리는 어제 회의를 했다(열었다)" / "The committee made a decision → 위원회가 결정했다" / "The data show a rapid increase → 데이터에 따르면 급격히 증가했다". metric
have_make_literal_count정량 검출. _source_anchor: 김정우 2007 · 이근희 2005 · see_scholarship: scholarship.md#6-명사화-표현-및-havemake-류-직역_
A-8. 이중 피동 "~되어진다" / "~지게 된다" [S1]
- 예: "판단되어진다" → "판단된다" / "판단한다"
- 처방: 가능하면 능동으로. 못 바꾸면 단일 피동.
A-9. "~에 의해" 피동문 [S2]
- 패턴: by-passive (영어 수동태 직역)
- 예: "AI에 의해 생성된 이미지" → "AI가 만든 이미지"
- 처방: 행위자를 주어로 복귀.
A-10. "~할 수 있다" 남발 [S2]
- 패턴: 가능형 서술 (영어
can/be able to) - 예: "효율을 높일 수 있다. 비용을 줄일 수 있다. 시간을 단축할 수 있다."
- 처방: 확정 서술 ("높인다", "줄인다")로 톤 전환. 꼭 가능성을 말할 때만 남김.
A-11. "~을 위해" 목적절 남발 [S2]
- 패턴:
X을 위해 Y한다(영어in order to) - 예: "고객 만족을 위해 노력한다" → "고객이 만족하도록 일한다"
A-12. "만들어지다" / "이루어지다" [S2]
- 패턴: 자동화된 피동
- 예: "합의가 이루어졌다" → "합의했다" / "합의에 이르렀다"
A-13. 명사 나열 (조사 생략) [S2]
- 패턴: 영어식 명사구를 조사 없이 붙임
- 예: "AI 기술 발전 속도 가속화" → "AI 기술의 발전 속도가 빨라지고 있다"
- 처방: 적절한 조사("의", "가", "를") 복원.
A-14. 접속부사 "그리고" 절 연결 [S2]
- 패턴: 영어
and처럼 "그리고"로 평문 연결 - 예: "그는 보고했다. 그리고 자리에 앉았다." → "그는 보고하고 자리에 앉았다."
- 처방: "-고", "-며", "-면서" 등 연결어미로 압축.
A-15. 추상 주어 + 만능 동사 [S2] · v1.1 신규
- 패턴: 영어
The X shows / provides / brings Y직역. 주어가 사건·현상이고 술어가 "보여준다·제공한다·가져온다·시사한다" - 예: "DeepSeek-V4의 등장은 ~을 보여줍니다" / "이 전략은 지형을 흔들고 있습니다" / "X는 Y를 제공합니다"
- 처방: 주어를 행위자(사람·팀·회사)로 돌리거나, 주어·동사 자체를 없애고 직접 서술. "DeepSeek는 ~ 원칙을 이렇게 증명했다" 식.
- v2.0 보강 — 사역·인지·발화 동사 3축 처방:
- (a) 사역 타동사형(
X made Y …) →X 때문에/덕분에 Y는 …또는X로 인해 Y는 …부사절·원인절 환원. 예: "The news made him happy → 그 소식을 듣고 그는 기뻤다"; "1997년 금융위기는 한국 노동시장에 급격한 변화를 가져왔다 → 1997년 금융위기로 한국 노동시장은 급격히 바뀌었다" - (b) 인지·발화 동사(suggest/show/indicate/reveal) →
…에 따르면 …이다또는…으로 …이 드러났다분리 구문. 예: "Recent research suggests that … → 최근 연구에 따르면 …이다 / 최근 연구를 통해 …이 드러났다" - (c) 'This book has 300 pages' 류 → 이중주어 구문 활용 ('이 책은 300쪽이다', '이 책은 300쪽을 가진다 X')
- _source_anchor: 이영옥 2001 · 김정우 2007 · see_scholarship: scholarship.md#1-무생물-주어--타동사-구문_
A-16. 영어 대명사 직역 (그/그녀/그것/그들) [S1] · v2.0 신규
- 패턴: 영어
he/she/it/they → 그/그녀/그것/그들을 1대1 매핑. 한국어는 (i) 영형(zero) 대명사를 통한 생략, (ii) 반복적 명사구의 재사용, (iii) 친족·지위 호칭으로 응결성(cohesion)을 확보. 한국어 '그/그녀'는 본래 19~20세기 번역 문학을 통해 도입된 인공 어휘에 가깝다. NMT/LLM 출력의 대명사 밀도가 비번역 한국어의 2~3배에 달함(보고서 §3.3.3 verbatim). - 예:
- "John was tired. He sat down. He sighed. He looked at his watch." → 직역 "존은 피곤했다. 그는 앉았다. 그는 한숨을 쉬었다. 그는 그의 시계를 보았다." → 자연 "존은 피곤했다. 자리에 앉아 한숨을 쉬고는 시계를 보았다."
- "Mary called her mother because she missed her." → 직역 "메리는 그녀가 그녀를 그리워해서 그녀의 어머니에게 전화했다." → 자연 "메리는 어머니가 그리워서 전화를 걸었다."
- "his hand / her hair" → 직역 "그의 손 / 그녀의 머리" → 자연 "손 / 머리" (거의 항상 잉여적)
- 처방:
- (a) 대명사 출현의 50~70%는 삭제 후보로 보고 문장 재구성
- (b) 화자 전환·장면 전환의 시점에서만 명사구 또는 호칭으로 명시
- (c) 'he/she'가 성별 모르는 일반인은 '그 사람' 또는 주어 생략. 'they'는 '그들'이 아니라 '사람들·우리·일부·어떤 이들'로 다양화
- 검출 임계: 한 단락(=문단) 내 인칭 대명사 ≥3회 시 가산 (pe_checklist PE4). metric
pronoun_densityz>2.0 (비번역 한국어 baseline 대비) 시 정점 가산. - _source_anchor: 김도훈 2009 통역과 번역 11(2): 3-19; Cho·Kim·Kim·Kim 2019 ACL GeBNLP arXiv:1905.11684 · see_scholarship: scholarship.md#3-대명사-직역-hesheitthey--그그녀그것그들_
A-17. (보류 — v2.0 hold) 무정물·추상명사 '-들' 복수 표지 기계적 부착
Hold 사유: v2.0 외부 회차(2026-05-07, 한국어 위키 6편)에서 양성 0건, v1.6 input 5편에서도 0건. 학술 anchor(전영철 2007 언어학 49 · 곽은주·진실로 2011 · 김순영 2012 · 김정우 2013)는 강하나, 우리 코퍼스에서 결정타 부재. NMT 원본 출력 회차(DeepL·Papago·Google Translate) 후 v2.1에서 동일 ID로 재평가 예정.
>
유지 자산: scholarship.md §4(전문 학술 인용 보존),metrics_v2.deul_overuse_rate함수와 무정물·추상 명사 사전 25종(검증용 정량 측정은 계속), 본 hold 결정 기록(promotion_decisions.md).
>
A-17 ID는 v2.1 부활을 위해 비워둠 — detector·rewriter 코드의 patternID 안정성 보존.
A-18. 관계대명사절 직역 — 긴 좌향 수식 (관형구 3중 이상 중첩) [S2] · v2.0 신규
- 패턴: 영어는 관계대명사절을 명사 뒤에 후치(right-branching)하지만, 한국어는 관형절을 명사 앞에 전치(left-branching). 영어 긴 관계절을 1대1 매핑하면 핵 어휘 도달 전 독자 작업기억 부담 폭증. NMT/LLM은 영어 SVO 구조를 가능한 유지하려 하므로 좌향 수식 누적이 빈번(박옥수 2018).
- 예:
- "He met a man who had once worked for the company that produced the chemical that caused the accident." → 직역 "그는 사고를 일으킨 화학물질을 생산한 회사에서 한때 일했던 한 남자를 만났다." → 자연 "그는 한 남자를 만났는데, 그 남자는 사고를 일으킨 화학물질을 만든 회사에서 한때 일했던 사람이었다." (관계절을 후치 동격절로)
- "He was too intelligent and perceptive not to feel the disappointment of his admirers from the 1930s." → 직역 "그는 1930년대부터 자기를 따랐던 사람들이 느낄 실망감을 눈치채지 못하기에는 너무 똑똑하고 예민했다." → 자연 "그는 워낙 똑똑하고 예민해서 1930년대부터 자기를 따랐던 사람들이 느낄 실망감을 눈치챘다."
- 처방:
- (a) 관계절이 3어절 이상이면 문장을 분리하거나 동격 후치 구문으로 변환
- (b) 'who, which, that'을 '~인 X', '~한 X' 식으로 직역하지 말고 '~는데, ~으며, 그 X는'으로 풀어쓰기
- (c) NMT 출력 검토 시 '~한 …의 …을 …한 …이/가'처럼 관형구가 3중 이상 중첩된 문장은 무조건 재구성 대상
- 검출 임계: 명사 앞 관형구 ≥3어절 시 가산 (pe_checklist PE6). metric
relative_clause_nesting(한 명사구 내 관형절 중첩 깊이) ≥3 문장 카운트, 한 문서 1회 초과 시 가산. A-18은 관형절 좌향 수식 단위, E-5(쉼표 분절 평균 길이)는 쉼표 단위 — 측정 차원 분리. 동시 위반 시 가중. - _source_anchor: 박옥수 2018 동아인문학 44: 151-171; 김채은 2021 21세기영어영문학회 34: 279-305 · see_scholarship: scholarship.md#5-관계대명사절-직역-긴-좌향-수식_
A-19. 이중 조사 결합 (-에서의·-에로의·-으로의·-에의·-으로부터의·-로부터의) [S2] · v2.0 신규
- 패턴: 근대 한국어가 일본어 'の(の/への/での)' + 영어 전치사구('of/in/to/from')의 영향으로 격조사를 이중·삼중 결합한 표현이 늘어남. 본래 한국어는 절·구로 풀어 쓰는 것이 자연스러움.
- caveat C5 명시 제외 — 단순 '~의'는 탐지 대상 아님: '~의' 자체가 일본어 번역투인지에 대해서는 학계 합의가 없다. 국립국어원과 김슬옹 세종국어문화원장은 '~의'가 15세기부터 한국어에 존재했다고 본다(보고서 caveat #5 verbatim). 본 패턴은 '~에서의·~에로의·~으로의·~에의·~으로부터의·~로부터의' 이중 결합만 S2 이상으로 본다.
- 예:
- "the meeting in the upper story of the bar" → 직역 "주점의 2층에서의 살림" → 자연 "주점의 2층에서 시작한 살림"
- "liberation from tension" → 직역 "긴장으로부터의 해방" → 자연 "긴장에서 벗어남, 긴장이 풀림"
- "the response to the questionnaire" → 직역 "설문지에의 응답" → 자연 "설문지에 대한 응답, 설문 답변"
- "destroyed by the bombing" → 직역 "폭격에 의해 끊어진" / "이번 기회를 통하여" → 자연 "폭격으로 끊어진 / 이번 기회에"
- 처방:
- (a) 이중 조사 결합('-에서의/-에로의/-으로의/-에의/-으로부터의/-로부터의')은 검색 후 일괄 점검 대상
- (b) 전치사구 'from/to/through/by/of'를 1대1 매핑하지 말고 문장 단위로 의미 재해석
- (c) 연속된 '의 의 의'는 거의 항상 부적절하므로 절·구로 풀어쓰기
- 검출 임계: metric
double_particle_count정규식 매칭(에서의|에로의|으로의|에의|으로부터의|로부터의). 한 문서 3회 초과 시 S2 가산. baseline 비번역 한국어 0~2회 추정. - _source_anchor: 김정우 2007 번역학연구 8(1): 61-82; 김순영 2012 새국어생활 22(1) · see_scholarship: scholarship.md#7-일본어영어식-조사-결합-에서의에로의으로의에의_
---
B. 영어 인용·용어 과다 — S2
B-1. 괄호 병기 관습 [S2]
- 패턴: 처음 등장할 때 모든 전문용어에 영어 병기
- 예: "인공지능(AI)은 거대언어모델(LLM)과 다르다."
- 처방: 해당 문서가 전문 독자 대상이면 1회만 병기, 이후 한국어만. 일반 독자 대상이면 영어 병기 자체를 최소화.
B-2. 영어 용어 비번역 [S2]
- 패턴:
pipeline,framework,leverage,seamless,robust등 한국어로 쓸 수 있는데 영어 그대로. - 예: "이 framework를 leverage하여" → "이 체계를 활용해"
- 예외: 고유명사·업계 표준 용어(Transformer, API, SDK 등)는 유지.
B-3. 과도한 영어 인용구 [S2]
- 패턴: 영어 문장을 인용문으로 그대로 박아넣고 번역도 병기
- 처방: 정말 원문 어감이 필요한 경우가 아니면 한국어로 풀어쓰고 출처만 병기.
B-4. "~라고 알려진", "~로 일컬어지는" [S3]
- 패턴: 영어
known as / so-called직역 - 예: "'AGI'라고 알려진 범용 인공지능" → "범용 인공지능(AGI)"
---
C. 구조적 AI 패턴 (서식·레이아웃) — S1~S2
C-1. 기계적 병렬 열거 [S1]
- 패턴: "첫째, ~. 둘째, ~. 셋째, ~."가 문단 전체를 지배.
- 처방: 3개 중 1~2개만 서술문으로 녹이거나, "우선 / 다음으로 / 마지막으로" 등으로 어휘 변주. 열거가 꼭 필요하면 유지하되 각 항목 길이·구조를 일부러 흐트러뜨림.
C-2. 과도한 불릿 리스트 [S2]
- 패턴: 에세이·칼럼·리포트에서 3개 이상 연속 불릿 블록.
- 처방: 불릿을 산문으로 "녹이기". 정말 나열이 의미 있는 지점만 남김.
C-3. 반복적 섹션 헤딩 [S2]
- 패턴:
## 도입 ## 본론 ## 결론같은 도식적 분절. - 처방: 산문형 글이면 헤딩 자체를 제거. 리포트형이면 헤딩 문구를 구체화("AI 규제의 세 가지 균열점").
C-4. 문단 첫 문장 요약 공식 [S2]
- 패턴: 매 문단 첫 문장이 그 문단의 요약(topic sentence). 영어 작문 교본식.
- 처방: 일부 문단은 사례·장면·인용으로 시작하도록 순서를 흐트러뜨림.
C-5. 이모지 남발 [S1]
- 패턴:
✅ 🚀 💡 ⚠️ 📊같은 이모지가 리스트 머리·헤딩·강조에 박혀 있음. - 처방: 에세이/리포트 문맥이면 전량 제거. SNS·제품 카피가 아닌 이상 AI 티가 극단적으로 강함.
C-6. 헤딩 아래 한 줄 요약 박스 [S2]
- 패턴: 모든 섹션 헤딩 직후 "이 섹션에서는 ~를 다룬다" 같은 안내문.
- 처방: 삭제. 본문이 바로 들어가야 한국어 글답다.
C-7. 문단 간 기계적 "먼저·반면·결국" 3단 공식 [S2] · v1.1 신규
- 패턴: 문단 문두가 순서대로 "먼저 ~ / 반면 ~ / 결국 ~" 또는 "첫째 ~ / 둘째 ~ / 마지막으로 ~"로 고정. 한국 필자도 가끔 쓰나, 3연속 이상이면 AI 특유.
- 예: 본 문서 v1 초안 (문단 2 "먼저", 문단 3 "반면", 문단 6 "결국")
- 처방: 3개 중 2개 삭제. 순서 의미는 문단 자체 흐름으로 전달. 문두 접속사 없는 문단도 섞음.
C-8. 대칭 대구 공식 "A인가, B인가" 반복 [S2] · v1.1 신규
- 패턴: 동일 문서에서 이항 대립이 3회 이상 평행구로 반복. 영어 수사학 직역.
- 예: "독점인가, 확산인가" / "전략가에게는 ~, 입안자에게는 ~" / "누가 더 ~, 누가 더 ~"
- 처방: 3개 중 2개는 비대칭으로 재배치. 한쪽만 질문형·다른 쪽은 서술형으로 섞거나, 한쪽을 더 길게 풀어쓰고 다른 쪽은 짧게.
C-9. 숫자 괄호 인덱싱 "1) 2) 3)" [S2] · v1.3 신규
- 패턴: 동일 문단 또는 인접 문장에서 항목을
1) ... 2) ... 3) ...형식으로 나열. C-1(첫째·둘째·셋째)·C-2(불릿)와 별개의 표기 시그니처. 한국어 인간 필자도 보고서에서 가끔 쓰지만, LLM 산출물에서는 3개 항목이 있을 때 거의 자동으로 숫자 괄호 인덱싱이 등장하는 빈도가 압도적으로 높음. - 예: "1) 표준화된 인프라가 일반화되면서 학습 데이터 확보가 용이해졌다. 2) 도메인 특화 LLM이 성숙하면서 비정형 텍스트의 활용 범위가 넓어졌다. 3) 클라우드 GPU 단가가 크게 하락하면서 자체 학습이 비용 측면에서 정당화 가능한 수준에 들어왔다."
- 처방: 3개 중 1개는 서술문으로 녹이고, 나머지 2개도 1)·2) 표기 대신 "우선~", "다음으로~" 형식으로 어휘 변주. 정말 동일 구조 나열이 의미 있을 때만 숫자 괄호를 유지하되 한 문서에 1회 이하.
C-10. 콜론 부제 헤딩 공식 "X: Y" 또는 "X: A에서 B로" [S2] · v1.3.1 신규
- 패턴: 헤딩에 거의 자동으로 콜론을 사용해 "메인 라벨: 부제" 또는 "메인 라벨: 주제 명사구" 형태로 구조화. C-3(반복 헤딩) 인접하지만 별개 — C-3는 도식적 분절(
## 도입 ## 본론 ## 결론)이고 C-10은 헤딩 자체에 메타 라벨 + 콜론 + 부제를 박는 공식. Gemini-우세 시그니처(회차 3 검증). - 예: "### 서론: 제조업의 미래, AI에 달려있다" / "### 본론 1: 빛과 그림자, 대기업과 중소기업의 디지털 격차" / "## 2026년 핀테크, '일상'을 넘어 '생태계'로 진화하다"
- 처방: 헤딩에서 콜론 + 부제 자체를 제거하고 단일 명사구·동사구로 압축. 정말 부제가 필요하면 (a) 본문 첫 문장에 녹이기, (b) 콜론 대신 — 또는 줄바꿈 활용. 한 문서에 콜론 부제 헤딩 1회 이하.
C-11. 연결어미 뒤 쉼표 [S1] · v1.6 신규
- 패턴: 연결어미(-고/-며/-지만/-면서/-아서·어서/-자/-는데) 직후에 쉼표가 따라옴. 한국어 인간 필자는 연결어미 자체가 호흡 단위를 만들어 추가 쉼표가 거의 불필요한데, AI는 영어 comma-after-conjunction 감각을 이식해 자동으로 쉼표를 박음. 분류 체계 전체 단일 지표 최강 분리도(KatFish 에세이 인간 4.10% vs AI 19.83%, 4.84배).
- 예: "AI는 빠르게 발전하지만, 기업의 대응은 더디다" / "데이터를 정제하고, 모델을 학습시킨다음, 결과를 검증한다" / "비용이 낮아지면서, 진입장벽이 사라졌다"
- 처방: 연결어미 뒤 쉼표를 일괄 제거. 호흡이 너무 길어지면 한국어식 절(節) 분할(마침표로 끊기) 또는 다른 위치(주절 경계)로 쉼표 이동. 한 문서 6+회 등장 시 S1, 3~5회는 S2로 강도 분기.
C-12. 쉼표 포함률 (문서 단위) [S2] · v1.6 신규
- 패턴: 전체 문장 중 쉼표를 1개 이상 포함하는 문장의 비율이 50%를 넘음. C-11(연결어미 뒤 위치 특이)과 측정 차원이 다름 — C-12는 문서 전체 분포. AI는 거의 모든 문장에 쉼표를 넣는 경향(KatFish 에세이 인간 26.31% vs AI 61.03%, 2.32배).
- 예: 한 문단 5개 문장 중 4~5개 모두에 쉼표가 박힌 상태(인간 평균은 5개 중 1~2개).
- 처방: 쉼표 1+ 문장 비율 50% 초과 시 일부 문장의 쉼표를 (a) 마침표 분할로 단문화, (b) 연결어미로 흡수, (c) 그냥 삭제로 전환. baseline 26~33% 기준 z>1.0 가산.
---
D. AI 특유의 관용구 (Signature Phrases) — S1
한국어 인간 필자가 거의 쓰지 않지만 LLM이 반복적으로 산출하는 상투구. 발견 즉시 교체.
D-1. 종결·요약류
- "결론적으로", "요약하면", "종합하면", "정리하자면"
- "~라고 할 수 있다" / "~라고 볼 수 있다"
- "~라 하겠다", "~라 할 것이다"
- "~에 다름 아니다"
- KatFish 검증 결산 lexicon 4종 (v1.6 보강): "결론적으로 / 따라서 / 이를 통해 / 그러므로" — Park et al. 보고서 lexicon-grounded 6대 지표 5번. LREAD Phase 2 루브릭에서 인간 판독 정확도 60→90% 상승의 핵심 항목. 이 4종 합산이 한 문서에 3회 초과 시 D-1 가산을 강화(S1 유지). "이를 통해"는 A-2(~를 통해 남발)와도 가산되며, "따라서·그러므로"는 H-1(문두 접속사)과 가산.
D-2. 의의·중요성 과장
- "매우 중요하다", "반드시 기억해야 한다"
- "시사하는 바가 크다", "주목할 만하다"
- "간과할 수 없다", "무시할 수 없다"
- "~의 지평을 연다", "~에 방점을 찍는다"
- "그 의미가 적지 않다", "의미심장하다"
D-3. 열거 도입
- "크게 세 가지로 나눌 수 있다"
- "다음과 같은 특징을 가진다"
- "다음과 같이 요약할 수 있다"
D-4. AI 티 특화
- "혁신적인", "획기적인", "전례 없는" (hype 어휘)
- Gemini-우세 hype 어휘 셋 (v1.3.1 보강): "압도적·막강한·폭발적·파격적·대대적·강력한·치열한·뜨거운"
- "압도적 1위 카카오뱅크는 ~ 막강한 월간 활성 이용자(MAU)"
- "파격적인 예적금 금리"
- "폭발적인 호응을 얻고 있다"
- "대대적인 개편이 필요합니다"
- "~의 가능성을 열어준다"
- "~의 새로운 장을 열다"
- "~시대가 도래했다"
D-5. 의인화된 추상 주어 [S2] · v1.1 신규
- 패턴: 사건·기술·개념을 주어로 삼아 인간 행위처럼 서술. AI가 글을 "무게감 있게" 보이게 하려는 기본 동작.
- 예: "두 지능의 충돌이 질문을 던집니다" / "AI 대전이 끝나지 않습니다" / "지능의 가성비가 증명합니다"
- 처방: 실제 행위자로 주어 교체("두 회사의 경쟁은", "엔지니어들은"), 또는 의인화 동사 약화("던집니다"→"남습니다"·"생깁니다"). 단, 상징적 제목·요약 1회 정도는 허용.
D-6. 완결 공식형 결말 "~할 때입니다 / 시점입니다" [S2] · v1.1 신규
- 패턴: 칼럼·리포트 마지막 문장이 "~해야 할 때입니다", "~로 나아갈 시점입니다", "~할 순간입니다" 공식.
- 예: "에이전트 정부의 시대로 나아가야 할 때입니다"
- 처방: 동일 의미를 구체 동사 단언으로. "에이전트 정부 단계로 넘어갈 때입니다" 정도까지는 허용(덜 과장). 한 문서에 한 번만.
D-7. 변환 공식 "X에서 Y로 / X을 넘어 Y로" [S2] · v1.3.1 신규
- 패턴: 패러다임 전환·진화·고도화를 표현할 때 거의 자동으로 사용. D-1·D-2·D-6와 별개의 결산/슬로건 공식. C-8(A인가 B인가, 질문형)과도 다른 시그니처 — 변환의 방향성을 강조. Gemini-우세 시그니처(회차 3 검증, 7회·2도메인 분산).
- 예: "'규모의 경쟁'에서 '전략의 경쟁'으로", "'지식 전달자'에서 '학습 조력자'로", "'무엇을'에서 '어떻게'로", "'데이터 조회'를 넘어 '맞춤형 금융 비서'로"
- 처방: 변환 공식을 직접 단언으로 (예: "'지식 전달자'에서 '학습 조력자'로" → "교사는 더 이상 지식 전달자가 아니다. 학생 곁에서 학습을 돕는다"). 한 문서에 변환 공식 1회 이하. 정말 패러다임 전환이 핵심 메시지일 때만 본문 결산에서 1회.
처방: 대부분 삭제. 의미가 필요하면 구체 명사·동사로 치환("중요하다"→"핵심이다" 혹은 구체 근거로).
---
E. 리듬·문장 길이 균일성 — S2
E-1. 문장 길이 표준편차 낮음
- 모든 문장이 30~50자 부근에 몰려 있음.
- 처방: 의도적으로 단문(10~15자) 1~2개를 문단마다 끼워 넣어 리듬 변주. 장문(80자+) 1개도 혼용.
E-2. 동일 종결어미 반복
- "~이다. ~이다. ~이다."
- "~한다. ~한다. ~한다."
- 처방: "~다"·"~았다"·"~인 것"·명사형 종결을 섞음. 인간 필자는 무의식적으로 변주함.
- v2.0 보강 — 진행형 '~고 있다' 자동 매핑 처방:
- 영어 진행형(be -ing)을 한국어 '~고 있다'로 자동 매핑하면 잉여(보고서 §3.8.4 verbatim — '지금 책을 읽는다 / 책을 읽고 있다' 모두 가능, 단순 시제로도 진행 의미가 표현됨).
- 진행형 '~고 있다' 발견 시 단순 시제로 환원 가능성 검토 (pe_checklist PE10). 예: "I have been thinking about it. → 그동안 그 일을 곰곰이 생각해 봤다" (
~해 오고 있다거부). - 한 단락 내 종결어미 '~다' 4문장 이상 연속 시 다양화 ('~었다·~ㄴ다·~는다·~기 마련이다·~ㄹ 것이다·~을 수 있다' 등) — pe_checklist PE9.
- metric
progressive_aspect_rate(~고 있다 빈도 / 전체 문장 수) >0.5 시 가산. - _source_anchor: 김혜영 2019 통번역교육연구 17(2): 133-162 doi:10.23903/kaited.2019.17.2.007 · see_scholarship: scholarship.md#8-종결어미시제서법-처리_
E-3. 모든 문단 3~4문장 공식
- 문단 길이도 균일.
- 처방: 1문장 문단 / 6문장 문단을 의도적으로 섞음.
E-4. 단문 일변도 (복문·중문 부재) [S2] · v1.5.1 신규
- 패턴: 문장 대부분이 단문(주어-서술어 1쌍)으로만 끊어져 있고 연결어미·관형절·인용절을 활용한 복문·중문이 거의 없음. "간결하게 써라" 지시를 받았거나 짧은 호흡을 의도한 AI 출력에서 빈출. 인간 필자는 단문과 복문을 무의식적으로 섞어 호흡을 만들기 때문에, 단문만 줄지어 나오는 리듬 자체가 시그니처가 된다. E-1(길이 균일성)과 짝패턴 — E-1은 길이의 표준편차, E-4는 구조의 단조성을 지적.
- 예: "AI는 빠르게 발전한다. 기업은 따라가야 한다. 시간이 없다. 데이터가 핵심이다. 인재도 부족하다."
- 비교(인간 톤): "AI가 빠르게 발전하는 가운데 기업은 따라가야 한다. 시간은 없고 데이터는 핵심이며, 인재마저 부족하다."
- 처방: 인접한 단문 2~3개를 연결어미("-며·-고·-는데·-면서·-자")·관형절("~하는 N", "~인 N")·인용절·조건절로 묶어 복문화. 단문 비중을 60% 전후로 조절하고 복문·중문을 30% 이상으로. 단문은 강조·전환·결정타에만 의도적으로 사용.
E-5. 쉼표 분절 평균 길이 (긴 절 구조) [S2] · v1.6 신규
- 패턴: 쉼표로 분절된 절(節)의 평균 어절 수가 길어짐. AI는 한 문장 안에 긴 부속절을 콤마로 이어 붙이는 영어식 long-sentence 구조를 산출(KatFish 에세이 인간 4.35어절 vs AI 8.56어절, 1.97배). E-4(단문 일변도)와 짝패턴이지만 반대 방향 — 짧으면 단문 일변도, 길면 영어식 long sentence, 두 극단 모두 AI 시그니처.
- 예: "AI 기술이 빠르게 발전하면서 산업 전반의 생산성이 높아지고 있는 가운데, 기업의 디지털 전환 속도가 가속화되고, 인재 확보 경쟁이 치열해지면서, 데이터 인프라 투자도 확대되고 있다." (한 문장 안 4개 절, 각 8~12어절)
- 처방: 평균 절 길이 7어절 초과 시 가산. 8어절 이상 절은 마침표로 분할하거나 영어식 부속절을 한국어 관형절로 압축. E-4와 동시 위반 시 가중.
E-6. 쉼표 전후 POS 다양성 높음 (구문 복잡도) [S2] · v1.6 신규 · 장르 가드
- 패턴: 쉼표 앞·뒤에 등장하는 품사(POS) 종류 수가 폭증. AI는 쉼표를 다양한 품사 경계에 무차별 삽입(주어·부사절·삽입절·접속사 뒤 등)해 POS 다양성이 매우 커짐(KatFish 에세이 인간 24.38 vs AI 59.39, 2.44배). 장르 가드 — 에세이·뉴스·블로그·QA·보고서 한정 적용. 시·소설 등 운문·문학 장르에서는 분리도 약함(시: 인간 23.13 vs AI 23.86, 1.03배).
- 예: 같은 문서 안에서 쉼표가 명사 뒤·부사 뒤·동사 뒤·관형사 뒤·인용 뒤·접속사 뒤 모두에 무차별 삽입.
- 처방: 쉼표 사용 위치를 (a) 주절 경계만, (b) 명백한 동격·삽입만으로 한정. 무차별 삽입 금지. baseline ~24~30(에세이/뉴스) 기준 z>1.0 가산.
E-7. 청자 경어법 일관성 손실 (해라/하게/하오/해요/합쇼체) [S2 · estimated] · v2.0 신규
- 패턴: 한국어는 교착어로서 종결어미가 (a) 문장종결법, (b) 화행, (c) 양태(modality), (d) 청자에 대한 공손성, (e) 화자–청자 관계까지 표시한다(보고서 §3.8.1 verbatim). 영어는 종결어미가 없어 어순·동사 굴절·양태조동사로 이를 표현하므로, 영한 번역·LLM 출력은 청자 경어법 일관성을 자주 잃는다. 해라체·하게체·하오체·해요체·합쇼체 4단계가 한 문서·대화 안에서 뒤섞임. E-2(동일 종결어미 반복)와 axis가 다름 — E-2는 단일 종결어미의 단조 반복, E-7은 격식 단계의 일관성 손실.
- estimated 플래그 (caveat C1): 김혜영 2019 본문 정량 수치(평서형 '-다' 출현 빈도 %)는 KCI ART002506702 영문 초록·키워드 기반 추론. PDF 직접 확보 전까지 임계는 'estimated' 유지.
- 예: 같은 대화 안에서 "도와주시겠습니까?(합쇼)" 다음에 "도와줘?(해라)"가 갑자기 등장; 같은 보고서가 한 문단은 "~합니다"(합쇼), 다음 문단은 "~한다"(해라)로 점프; "Will you help me? → 당신은 나를 도와주겠습니까?"식 격식 과잉 직역.
- 처방:
- (a) 문서 시작 시 청자 등급(해라/하게/해요/합쇼)을 결정하고 일관 유지
- (b) "Will you help me?"는 관계·공손도에 따라 "좀 도와주시겠어요? / 도와줄래?" 등 적절한 한 단계만 선택
- (c) 화행·양태(might/may)는 단조 처리("~수 있다") 거부 — "~을지 모른다·~을 가능성도 있다·~을 수도 있겠다·~을 법하다"로 다양화
- 검출 임계: 장르 가드 — 대화·구어 텍스트(소설 대화·인터뷰 트랜스크립트·에세이 내 인용 대화) 한정 적용. 보고서·정책문 등 격식체 단일 장르는 본 패턴 미적용 (이미 합쇼체로 일관). 한 문서·대화 안에 2단계 이상 격식 혼재 발견 시 S2.
- _source_anchor: 김혜영 2019 통번역교육연구 17(2): 133-162 doi:10.23903/kaited.2019.17.2.007 · see_scholarship: scholarship.md#8-종결어미시제서법-처리_
---
F. 과도한 수식·중복 — S2
F-1. 정도부사 중독
- "매우", "정말", "진짜로", "대단히", "극히"
- 처방: 대부분 삭제. 강조가 필요하면 구체 수치·사례로 대체.
F-2. 동의어 이중 수식
- "중요하고 핵심적인 역할"
- "새롭고 혁신적인 접근"
- "지속적이고 꾸준한 노력"
- 처방: 두 수식어 중 하나만 남김.
F-3. 기능+역할 복합구
- "~로서의 역할과 기능"
- "~의 의미와 가치"
- 처방: 하나만.
F-4. 과잉 접두·접미
- "~적 측면", "~적 관점"
- "~성(性)", "~화(化)" 남발
- 예: "근본적 관점에서 구조적 변화가 필연적이다" → "구조가 근본부터 바뀐다"
- 한자어 명사화 접미사 3종 명시 (v1.6 보강): "-성(性) · -적(的) · -화(化)" — KatFish 보고서 hanja_nominalizers 정식 명시. 이 3종 결합 어휘 밀도가 한 문서 12회 초과 시 S2 강화. F-5(~적 N 복합 추상어 체인)는 "-적" 접미사의 특수 케이스로 그대로 분리 유지. 처방은 본 항목과 동일 — (a) 동사·형용사 어근, (b) 구체 명사로 해체.
- 영어 명사화 접미사 4종 통합 (v2.0 보강): 영어 명사화 접미사
-tion · -ment · -ness · -ity가 누적된 영어 명사구의 한국어 명사 직역도 동일 처방으로 묶음. 예: "the implementation of the policy → 정책 시행" 또는 "정책을 시행하기" (보고서 §3.6 verbatim 처방). 영어 명사화 4종이 한국어 한자어 명사로 1대1 매핑된 경우 동사·형용사 어근으로 환원. 한자어 3종(-성·-적·-화) + 영어 4종(-tion·-ment·-ness·-ity) 통합 가산 임계는 위 v1.6 임계(한 문서 12회 초과 S2 강화) 그대로 유지. - _source_anchor: 김정우 2007 번역학연구 8(1): 61-82 · see_scholarship: scholarship.md#6-명사화-표현-및-havemake-류-직역_
F-5. "~적 N" 복합 추상어 체인 [S2] · v1.1 신규
- 패턴: 명사 앞 "~적 N" 형태가 한 문서에 3회 이상 반복. F-4와 달리 추상 관형("적 측면/관점")이 아닌 구체 명사 앞 "~적 N" 체인. 원문의 지적 권위를 AI가 흉내 낼 때 빈출.
- 예: "에이전트적 자율성", "기술적 안정성", "경제적 자립", "기술적 토대", "시스템적 접근", "구조적 변화"
- 처방: 해당 "~적 N"을 (a) "~로서의 N" ("에이전트로서의 자율성"), (b) 동사구 ("기술이 얼마나 안정적인가"), (c) 구체 명사 ("토대") 중 하나로 해체. 문서 전체에서 "~적 N" 밀도를 절반 이하로.
---
G. 과도한 Hedging (완곡) — S2
G-1. 추측·관측형 종결
- "~할 수 있을 것으로 보인다"
- "~인 것으로 판단된다"
- "~라고 여겨진다"
- "~인 듯하다"가 모든 문장 끝에 붙음
- 처방: 단언할 수 있는 곳은 단언. hedging은 정말 불확실한 지점에만.
G-2. 이중·삼중 완곡
- "~할 가능성이 있을 수 있다"
- "~로 보여질 수 있다"
- 처방: 하나만 남김.
G-3. 안전 균형 lexicon (Safe Balance Score) [S2] · v1.6 신규
- 패턴: "양쪽 모두 / 두 가지 모두 / 장점도 있지만 / 신중하게 / 균형" 등 균형·양면성·완곡 어휘 빈도가 높음. KatFish 보고서 lexicon-grounded 6대 지표 6번. G-1(추측·관측형 종결어미)과 측정 차원이 다름 — G-1은 종결어미 단위, G-3는 lexicon 단위. LREAD 루브릭의 "위험 회피·양면 제시" 항목과 직결.
- 예: "양쪽 모두 일리가 있다 / 두 가지 모두 검토할 필요가 있다 / 장점도 있지만 단점도 있다 / 신중하게 접근해야 한다 / 균형 잡힌 시각이 중요하다"
- 처방: 균형 어휘를 (a) 한쪽 단언, (b) 구체 사례 비교, (c) 조건부("X일 때는 A, Y일 때는 B")로 변환. "신중하게·균형"은 구체 동사·기준으로 치환. 한 문서 lexicon 5종 합산 4회 초과 시 S2 가산. 정책·보고서 장르 한정(에세이·시는 baseline이 다름 — 향후 metric-engineer가 장르별 보강).
---
H. 접속사 남발 — S2
H-1. 문두 접속사 과다
- 매 문장·매 문단 시작에 "또한", "따라서", "즉", "나아가", "아울러", "게다가", "더욱이"
- 처방: 70% 이상 제거. 논리 흐름은 문장 내용 자체로 드러나야 함. 정말 역접·인과 강조가 필요할 때만.
H-2. "하지만"과 "그러나" 혼용 남발
- 역접이 문단마다 등장.
- 처방: 반절 이상 삭제. 대비가 자명하면 접속사 없이도 통함.
H-3. "이는 ~" 지시 반복
- "이는 ~을 의미한다"
- 메타 진입 변종 (v1.3 보강): "이 점에서 ~ / 이 관점에서 보면 ~ / 이 말은 ~" — 본진 H-3와 같은 기능(앞 문장을 받아 부연 설명)이지만 형태소가 다른 결합형
- "이 관점에서 보면 AI 시대 유망 직무도 다시 보인다"
- "이 말은 결국 기술 도입보다 인력 전환이 더 큰 병목이 될 수 있다는 뜻이다"
- "이 점에서 앞으로 강해질 인재는 크게 다섯 부류다"
- 처방: 앞 문장과 붙이거나 구체 서술로 치환. 결합형도 동일 처방 — 메타 진입 자체를 삭제하고 본 서술로 직진.
H-4. 재정의 접속사 "즉" 남발 [S2] · v1.1 신규
- 패턴: 영어
i.e./that is직역. 보충 설명이 필요할 때마다 "즉"을 앞에 붙임. - 예: "AI 민주화, 즉 경제성 측면에서"
- 처방: "곧", "말하자면", "다시 말해", "바꿔 말하면"으로 어휘 변주. 또는 아예 생략하고 앞뒤를 쉼표로만 연결. 한 문서에 "즉" 2회 이하로 제한.
---
I. 형식명사·의존명사 과다 — S2
I-1. "것이다" 종결 남발
- "~한 것이다", "~일 것이다"가 문단의 대표 종결.
- 처방: 확정 서술로. "~다"로 끝맺음.
I-2. "점", "바", "수", "데" 반복
- "주목할 점은", "나아갈 바는", "할 수가 있다", "하는 데에"
- 결합형 변종 (v1.3 보강): "X은 ~라는 점에 있다" 강조 위치 서술
- "핵심은 진입장벽이 빠르게 낮아지고 있다는 점에 있다"
- "의의는 표준화가 사업장별로 들쭉날쭉하다는 점에 있다"
- "주목할 부분은 수익 모델이 정착되지 않았다는 점에 있다"
- 처방: 구체 명사·동사로 치환 또는 삭제. 결합형은 "X은 ~다" 형태 단언으로 직결.
I-3. "~라는 것"
- "변화가 크다는 것이다."
- 결말 단언 변종 (v1.3 보강): "~라는 뜻이다 / ~다는 뜻이다" — GPT가 결산 문장을 형식명사로 마무리할 때 거의 자동으로 등장
- "기술 도입보다 인력 전환이 더 큰 병목이 될 수 있다는 뜻이다"
- "한국에서는 이 문제가 더 민감하다는 뜻이다"
- "더 큰 시장은 응용 산업에서 나올 가능성이 높다는 뜻이다"
- 처방: "변화가 크다." (종결어미 직결). 결말 변종은 "~다" 직접 종결로 (예: "병목은 인력 전환이다"). 한 문서에 형식명사 결산("~다는 것이다 / ~다는 뜻이다 / ~다는 점이다") 합산 2회 이하.
I-4. "~할 필요가 있다" + 정책 보고서 권고형 결말
- 영어
should/need to직역. - 권고형 결말 변종 (v1.3.1 보강): "~해야 한다 / ~해야 합니다"가 정책·보고서 결말마다 자동 등장. 한 문서에 5회 초과 시 S2 강화 (자동 생성 시그니처).
- "공유 플랫폼을 구축해야 한다 / 바우처 지원 사업을 대폭 확대하여 ~ 낮춰야 한다 / 핵심 인재를 양성하는 것이 중요하다"
- "균형을 맞춰야 합니다 / 구축해야 합니다 / 마련해야 합니다 / 지원해야 합니다"
- 처방: "~해야 한다 / ~해야 합니다"를 (a) 구체 동사 단언("~를 시급히 추진"), (b) 주체 명시 동사("정부는 ~를 도입한다"), (c) 조건문("~이 충족되면 ~가 가능하다") 중 하나로 변주. 한 문서 5회 초과 권고형 결말은 회피.
I-5. "~이/가 필요하다"
- "혁신이 필요하다", "변화가 필요하다"
- 처방: 누가 무엇을 해야 하는지 주어·동사로 구체화.
I-6. "~능력" 추상명사 연쇄 [S2] · v1.1 신규
- 패턴: "N 능력"이 한 문서에 3회 이상 반복되며 동사 대신 명사구로 능력을 서술. 영어
ability to X / X capability직역 감성. - 예: "사고 능력", "워크플로우 수행 능력", "장기 문맥 유지 능력", "추론 능력"
- 처방: 동사형으로 풀기. "사고 능력은 뛰어나다" → "잘 사고한다" / "사고의 수준이 높다". "워크플로우 수행 능력" → "워크플로우를 얼마나 잘 처리하는지". 한 문서에 "~능력" 2회 이하로 제한.
---
J. 시각 장식 남용 — S2~S3
J-1. 과도한 볼드
- 문장마다 핵심 단어 볼드.
- 처방: 본문에서 볼드는 거의 제거. 시각적 소음만 발생.
J-2. 따옴표 과다
- 개념어·강조어에 "" 남발.
- 빈도 임계 명시 (v1.3.1 보강): 한 문서에 따옴표 강조 어휘 5회 초과 시 S2 강화. Gemini는 한 문서에 17~33회 사례(예: "'옥석 가리기'·'금융 슈퍼앱'·'데이터 피로감'·'규제 샌드박스'·'무대 위의 현자'·'곁에서 돕는 안내자'·'학습 경험 설계자'").
- 처방: 진짜 인용·특수 용례에만 한정. 개념어 강조는 (a) 본문 흐름에 녹이거나 (b) 첫 등장 시 1회만 따옴표 사용 후 이후 한국어 평문으로.
J-3. 대시(—) 남용
- 영어 em-dash 스타일 부가 설명.
- 예: "AI는 도구 — 그 이상도 이하도 아닌 — 이다"
- 처방: 쉼표·괄호·별도 문장으로 분해. 1문서에 1~2회 이하.
J-4. 괄호 부연 과다
- "(이는 ~을 의미한다)" 같은 부연이 반복.
- 처방: 괄호 부연 대부분 본문화 또는 삭제.
---
탐지 출력 스키마 (Detector → Rewriter 공유 계약)
탐지기는 다음 JSON을 생산한다:
{
"meta": {
"input_length": 1820,
"detected_count": 37,
"ai_tell_density": 0.203,
"severity_weighted_score": 71.5
},
"findings": [
{
"id": "f001",
"category": "A-2",
"category_label": "번역투: ~를 통해 남발",
"severity": "S1",
"text_span": "데이터 분석을 통해",
"start": 142,
"end": 153,
"reason": "'통해'가 본문에서 6회 반복되어 경로 서술이 기계적",
"suggested_fix": "데이터를 분석해서"
}
],
"category_summary": {
"A": 12, "B": 3, "C": 2, "D": 8, "E": 1,
"F": 4, "G": 2, "H": 3, "I": 1, "J": 1
}
}severity_weighted_score: S1=5, S2=2, S3=0.5 가중 합. 0~100 스케일로 정규화.ai_tell_density: 탐지 span 총 글자 수 / 전체 글자 수.
post-editese 3축 — metric-only 트랙 (v2.0 도입)
중요: post-editese 3축(simplification·normalisation·interference)은 본진 패턴 ID 미부여 상태로 운영한다. 이유는 caveat C3 verbatim — "Toral(2019)은 en→de, de→en, es→de, en→fr, zh→en의 5개 언어쌍을 다뤘고, 한국어는 포함되지 않았다. 한국어에 대한 동일 결론은 합리적 추론이지만 정량적 검증은 미수행 상태다." 따라서 본진 패턴 ID는 토큰·구문 매칭 가능한 검증 시그널만 담고, 3축 합성 신호는 metric-only로 분리한다.
references/metrics_v2.py 14개 신규 함수가 3축을 운영한다(모든 metric에 speculative: true 플래그 권고):
- simplification 축:
lexical_diversity_ttr·lexical_density·ending_diversity(Baker 1993; Toral 2019). - normalisation 축:
normalisation_score(평서형 -다/된다/이다 집중률) ·da_streak_rate(-다 4문장 연속 streak 카운트) (Baker 1993). - interference 축: T1~T8 8개 검출 시그널 +
interference_index합성 (Toury 1995 law of interference) —inanimate_subject_rate(T1↔A-15·D-5) ·by_passive_count/double_passive_count(T2↔A-8·A-9·A-12) ·pronoun_density(T3↔A-16) ·deul_overuse_rate(T4↔A-17 hold, 검증용 측정 유지) ·relative_clause_nesting(T5↔A-18) ·have_make_literal_count(T6↔A-7·F-4) ·double_particle_count(T7↔A-19) ·progressive_aspect_rate(T8↔E-2·E-7).
본진 패턴 → metric 연계는 양방향이다. 패턴 위반 카운트가 임계 초과면 detector·rewriter가 본진 ID로 처방하고, 동시에 metric 합성 점수가 baseline 대비 이상치면 reviewer가 추가 검증한다. 한국어 baseline은 metric-engineer가 비번역 한국어 corpus(Sejong 등) 기준 산출한다.
버전 관리
- v2.0 (2026-05-07): 본진 신규 5건 + 본진 보강 4건 + post-editese metric-only 트랙 도입 — 한국어 번역투 종합 연구보고서(540줄, 4기 1994~ AI 융합 계보) + 보고서 §III.3 8유형 통합 + Toral 2019 post-editese:
- 본진 신규 4건:
A-16영어 대명사 직역 [S1, 김도훈 2009 + Cho et al. 2019 ACL] ·A-18관계절 좌향 수식 [S2, 박옥수 2018 + 김채은 2021] ·A-19이중 조사 결합 [S2, 김정우 2007 + 김순영 2012, caveat C5로 단순 ~의 명시 제외] ·E-7청자 경어법 일관성 손실 [S2 estimated, 김혜영 2019, caveat C1로 estimated 플래그] - 본진 hold 1건:
A-17무정물·추상명사 '-들' 부착 [학술 anchor 곽은주·진실로 2011 + 전영철 2007 + 김순영 2012 강함, 다만 외부 회차(2026-05-07 위키 6편) + v1.6 input 5편 모두 양성 0건 → NMT 원본 출력 회차 후 v2.1 재평가. ID 비워둠 — patternID 안정성 보존. metricdeul_overuse_rate+ 사전 25종은 검증용 보존] - 본진 보강:
A-15에 사역 타동사형·인지·발화 동사·이중주어 구문 3축 처방 추가(이영옥 2001 + 김정우 2007) ·A-7에 light verb construction 일반화(have/make/take/give + 명사) 처방 + 5건 verbatim 예문(김정우 2007 + 이근희 2005) ·F-4에 영어 명사화 접미사 4종(-tion/-ment/-ness/-ity) 한국어 명사 직역 통합 처방(김정우 2007) ·E-2에 진행형 '~고 있다' 자동 매핑 처방 추가(김혜영 2019) - post-editese metric-only 트랙: simplification·normalisation·interference 3축은 본진 ID 미부여,
metrics_v2.py14개 신규 함수로 운영. caveat C3에 따라 모든 metric에speculative: true플래그 권고. 본진 패턴 → metric 양방향 연계 - 외부 SSOT scholarship.md: 학술 전문(8유형 한국 번역학계 계보 + Baker·Toury·Laviosa·Chesterman·Toral 등 국제 이론 + 보고서 caveat 6건 verbatim)을 외부 파일로 분리. 본진 SSOT는 패턴 행마다
source_anchor+see_scholarship한 줄 메타로 가리킴 — 본진 슬림성 유지 - 카테고리 호환성: A·E 카테고리만 확장(A-15→A-19, E-6→E-7). 기존 A-1~A-15·E-1~E-6 본문 무수정. 새 K 카테고리 신설 거부 — 본진 패턴 ID 참조 안정성 보존
- caveat 적용 게이트: C1(김혜영 2019 정량 미확인 → E-7 estimated 플래그) · C2(NMT 마케팅 편향 → 모델별 가중치 거부) · C3(post-editese 한국어 미검증 → metric-only 트랙) · C5(단순 ~의 학계 합의 부재 → A-19 정의에서 명시 제외) · C6(LLM 빠른 진화 → 'valid as of 2026-05' 명기)
- 분류 체계의 새 차원: v2.0은 한국 번역학계 정통성 계보(이영옥 2001~김혜영 2019)를 본진에 통합한 첫 회차. v1.6의 KatFish/LREAD 외부 정량 신호와 결합하여 이론적 토대(8유형) + 정량 검증(KatFish) + 컴퓨테이션 검출(metric_v2) 3축으로 확장
- v1.6 (2026-05-06): 본진 신규 5건 + 본진 보강 2건 + hold 2건 — 외부 정량 연구(KatFish, Park et al. 인간 470 vs LLM 1,624편 / 에세이·시·초록 + LREAD 인간 판독 실험) 기반 9건 후보 중 7건 본진 반영, 2건 풀 보존:
- 본진 신규:
C-11연결어미 뒤 쉼표 [S1, 4.84배 분리도 — 단일 지표 최강] ·C-12쉼표 포함률 [S2, 2.32배] ·E-5쉼표 분절 평균 길이 [S2, 1.97배 · E-4 짝패턴 반대극] ·E-6쉼표 전후 POS 다양성 [S2, 2.44배 · 에세이/뉴스 한정 장르 가드] ·G-3안전 균형 lexicon [S2 · 정책·보고서 장르 한정] - 본진 보강:
D-1에 KatFish 검증 결산 lexicon 4종("결론적으로·따라서·이를 통해·그러므로") 정식 인용 + 합산 3회 초과 임계 + A-2·H-1과 가산 명시 ·F-4에 한자어 명사화 접미사 3종("-성·-적·-화") 정식 명시 + 한 문서 12회 초과 S2 강화 임계 - hold (본진 미등재): BN/VX 띄어쓰기 규칙성(Park et al. 정량 셀 미공개, 사용자 코퍼스 baseline 확보 후 v1.7 검토) · 페르소나-레지스터 불일치(v1.5 monolith fast 1콜 + author-context 미주입과 충돌, opt-in 메타 부스터 설계 정리 후 재검토). 후보 발자취는
_workspace/v1.6-2026-05-06/에 보존 - 분류 체계의 새 차원: v1.6은 외부 학술 연구의 정량 신호를 본진에 통합한 첫 회차. 연결어미 뒤 쉼표 4.84배 분리도는 v1.1~v1.5.1까지 통틀어 가장 강한 단일 지표
- v1.5.1 (2026-04-27): 본진 신규 1건 —
E-4단문 일변도 (복문·중문 부재) [S2]. 사용자 관찰: "지나친 단문은 AI 티가 난다. 사람이 작성할 때는 적절한 단문과 복문을 섞는다." E-1(문장 길이 표준편차)과 짝패턴이지만 별개 시그니처 — E-1은 "30~50자에 다 몰림", E-4는 "구조 자체가 단순 단문만". 인간 필자가 무의식적으로 만드는 단문+복문 혼합 리듬을 모사하지 못하는 AI 출력의 약점을 분류 체계로 명시화.
- v1.3.1 (2026-04-25): 본진 신규 2건 + 본진 보강 3건 — 사용자 제공 Gemini API 키로 직접 호출한 회차 3 데이터(Gemini Pro 2.5 4편 약 10,058자) 분석 결과:
- 본진 신규:
C-10콜론 부제 헤딩 공식 [S2] ·D-7변환 공식 'X에서 Y로' [S2] (둘 다 Gemini-우세 시그니처) - 본진 보강:
D-4Gemini hype 어휘 셋 추가 (압도적·막강한·폭발적·파격적·대대적·강력한) ·J-2빈도 임계 명시(한 문서 5회 초과 S2 강화) ·I-4권고형 결말 변종 추가 (~해야 한다·~해야 합니다, 정책 보고서 5회 초과 임계) - 회차 2 hold 후보 검증: GPT 9회+ 등장한 "결국" 문두 단언이 Gemini 4파일에서 1회만 재현. "A가 아니라 B" 결산 대구도 GPT 7회+ vs Gemini 2회. 5+ 콤마 나열은 Gemini 0회. 회차 2 hold 후보 3건 모두 GPT-우세 시그니처로 추정 — 풀에 hold 유지하면서 status_reason 갱신, 회차 4 국내 모델 검증 시 'GPT-특유' 메타 분류 검토
- 새 hold 후보 1건:
cand-C-2026-011굵은 번호 부제 (Gemini 1파일 4회, Gate 1.2 분산 미달) - 분류 체계의 새 차원 신호: 회차 1·2·3을 거치며 분류 체계에 "모델 우세 분포" 메타데이터 도입 필요성 부상 (v1.4 검토 사항)
- v1.3 (2026-04-25): 본진 신규 1건(C-9) + 본진 보강 3건(I-2 회차 1·I-3·H-3 회차 2), 그리고 서브 패턴 발굴 운영 체계 도입. 본진 신규/보강과 운영 인프라 확장이 함께:
- v1.1 (2026-04-24): 실전 1호(AI 전략 칼럼 윤문) 자기 재감사 결과, 재현 2회+ 패턴 7건 승격:
A-15추상 주어 + 만능 동사 (X가 Y를 보여준다/제공한다)C-7문단 문두 "먼저·반면·결국" 3단 공식C-8대칭 대구 공식 "A인가, B인가" 반복D-5의인화된 추상 주어 ("두 지능의 충돌", "AI 대전")D-6완결 공식형 결말 "~할 때입니다 / 시점입니다"F-5"~적 N" 복합 추상어 체인 (에이전트적 자율성·기술적 토대)H-4재정의 접속사 "즉" 남발- v1.3 (2026-04-25): 본진 신규 1건 (C-9 숫자 괄호 인덱싱) + 본진 보강 1건 (I-2 결합형 변종), 그리고 서브 패턴 발굴 운영 체계 도입. v1.2 이후 멈춰 있던 패턴 발굴이 새 인프라로 깨진 회차:
- 본진 신규:
C-9숫자 괄호 인덱싱 "1) 2) 3)" [S2] —_workspace/taxonomy_changelog.md회차 1에서 풀 후보cand-C-2026-001이 6게이트 통과 후 승격 - 본진 보강:
I-2시그니처 예문에 "X은 ~라는 점에 있다" 결합형 변종 4건 추가 — 풀 후보cand-I-2026-003이 Gate 2.2(본진 변종)에서merged처리되며 흡수 - 운영 인프라 5종 신설:
- candidate 풀 신설 (
references/pattern-candidates.md) — detector·rewriter·naturalness-reviewer가 미분류 의심 패턴을 단일 그릇에 누적. 임시 ID(cand-{대분류}-{YYYY}-{NNN})·4상태(pending/promoted/rejected/merged)·기각 사유 5종 라벨·90일 미재현 자동 만료 정책 - 3개 에이전트 적재 채널 명문화 — detector(미분류 span)·rewriter(윤문 저항·반복 잔존)·naturalness-reviewer(외부 시각, voice profile 미주입)에 풀 적재 트리거·절차 추가. 적재 실패는 메인 파이프라인 막지 않음
- taxonomist 풀 운영자 역할 추가 — 4가지 trigger(사용자 명시 / pending 10건 / 단일 후보 occurrences ≥ 3 / 외부 PR) 기반 점검. 점검 6단계 절차와 changelog 표준 형식 명문화
- 외부 샘플 수집 파이프라인 (
references/sample-collection.md) — 4축 다양성 매트릭스(모델·장르·길이·작가), 4종 채널(사용자 자발·합성 샘플·공개 데이터·외부 contributor), 익명화·저작권 5대 정책 - 승격 자동 검증 체크리스트 (
references/promotion-checklist.md) — 6개 게이트(사전 점검·재현·본진 중복·분류 적합성·처방 적합성·본진 위계). 일부 게이트(0.2·0.3·1.1·1.2·5.2)는 향후 스크립트 자동화 가능 - v1.3 발행 전 파일럿 회차 결과:
- 회차 1 (인프라 검증, 합성 샘플 2건): 미분류 후보 3건 발견 → promoted 1건(C-9 숫자 괄호 인덱싱) · hold 1건(메타 진입 '~을 살펴보면', Gate 1.3 분산 미달) · merged 1건(I-2 결합형). 인프라 작동 확인.
- 회차 2 (외부 진짜 데이터, 뉴스핌 [AI로 읽는 경제] 시리즈 ① ② — ChatGPT 작성 명시 GPT 출력): 미분류 후보 5건 발견 → merged 2건(I-3 보강 '~다는 뜻이다' 결말 변종, H-3 보강 '이 점에서·이 관점에서·이 말은' 메타 진입 변종) · hold 3건(H-N 후보 '결국' 문두 단언 9회+, D-N 후보 'A가 아니라 B' 부정-긍정 대구 7회+, C-N 후보 5~8개 콤마 빠른 나열 4회). hold 3건은 Gate 1.3 분산 보호장치가 진짜 외부 데이터에서 정확히 작동한 결과 — 같은 GPT·같은 기자 시리즈의 노이즈가 본진을 오염시키지 않으면서 다음 회차에 다른 모델·다른 작가 데이터에서 재현되면 즉시 promoted 가능한 강력 후보로 풀에 누적
- v1.2 (2026-04-25): Issue #1(simonsez9510) 후속 — 패턴 신설 0건, 권한 위계와 운영 체계 추가:
- 권한 위계 §1~§6 신설 — 객관 분류 vs 작가 voice profile의 권한 경계 명문화. opt-in 명시 주입, 패턴 ID 단위 무력화만 허용, 자유 텍스트 mandate 금지, A-8·C-5·D-1~D-6 무력화 불가, naturalness-reviewer 분리 검증층 보존, 회귀 게이트 정책
- 임계 완화 multiplier 캡표 — 일반 ≤ 2.0, D-1~D-6 ≤ 1.5, A-8·C-5 = 1.0 고정 (임계 우회를 통한 사실상 무력화 방지)
- `author-context.yaml` 스키마 신설 (
references/author-context-schema.md) — opt-in voice profile 주입 양식, Schema validator 책임(무력화 불가 disable 거부, multiplier 캡 위반 거부, prompt injection escape character 검증), Telemetry 정책(voice_profile_log.json) - 에이전트 정의 갱신 — detector·rewriter·auditor에 voice profile 주입, naturalness-reviewer 의도적 미주입 명문화
- 경로 토큰화 — SKILL.md 절대 경로 제거,
_workspace/는 cwd 기준 - 다운스트림 caller reference —
references/proposals/(PR #3, simonsez9510 어댑터 reference, 메인테이너 SSOT 외부 격리) - 확장 원칙: 실전 입력에서 재현 2회 이상 + 인간 필자가 거의 안 쓰는 패턴만 서브 항목 추가.
{
"version": "v2.0-baseline-diff-2026-05-07",
"source": "Placeholder. Toral 2019 simplification·normalisation·interference 정의 + 보고서 T1~T8 ko_manifestation 추정치. 비번역 한국어 (Sejong corpus·국립국어원 모두의 말뭉치 등) 정밀 측정은 별도 calibration 회차에서 수행.",
"notes": "metric-engineer(Phase 3b) 산출. ALL cells carry _placeholder: true. Phase 6 integrator는 본진 baseline.json에 merge할 때 placeholder 플래그를 반드시 보존하고, calibration 완료 셀만 플래그를 해제한다.",
"calibration_due": true,
"genres": {
"essay": {
"lexical_diversity_ttr": {"mean": 0.62, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "simplification", "interpretation": "low = AI-like (repetition)"},
"lexical_density": {"mean": 0.30, "stdev": 0.07, "_placeholder": true, "calibration_due": true, "axis": "simplification", "interpretation": "low = AI-like (function-word heavy)"},
"ending_diversity": {"mean": 0.55, "stdev": 0.12, "_placeholder": true, "calibration_due": true, "axis": "simplification", "interpretation": "low = monotonic endings"},
"normalisation_score": {"mean": 0.50, "stdev": 0.15, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "interpretation": "high = AI-like (-한다/-된다/-이다 concentration)"},
"da_streak_rate": {"mean": 0.4, "stdev": 0.6, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "unit": "streaks_per_doc", "interpretation": "high = AI-like"},
"inanimate_subject_rate": {"mean": 0.10, "stdev": 0.06, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T1", "interpretation": "high = AI-like (translationese)"},
"by_passive_count": {"mean": 0.5, "stdev": 1.0, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2a", "unit": "per_doc", "interpretation": "high = AI-like"},
"double_passive_count": {"mean": 0.2, "stdev": 0.6, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2b", "unit": "per_doc", "interpretation": "high = strong S2 signal"},
"pronoun_density": {"mean": 0.012, "stdev": 0.010, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T3", "interpretation": "high = AI-like (he/she literal mapping)"},
"deul_overuse_rate": {"mean": 0.005, "stdev": 0.008, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T4", "interpretation": "high = AI-like (-들 over-use)"},
"relative_clause_nesting": {"mean": 0.3, "stdev": 0.5, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T5", "unit": "sentences_per_doc", "interpretation": "high = AI-like (left-modifier overload)"},
"have_make_literal_count": {"mean": 0.4, "stdev": 0.8, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T6", "unit": "per_doc", "interpretation": "high = AI-like"},
"double_particle_count": {"mean": 0.3, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T7", "unit": "per_doc", "interpretation": "high = AI-like"},
"progressive_aspect_rate": {"mean": 0.10, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T8b", "interpretation": "high = AI-like (~고 있다 literal mapping)"}
},
"news": {
"lexical_diversity_ttr": {"mean": 0.65, "stdev": 0.07, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"lexical_density": {"mean": 0.34, "stdev": 0.07, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"ending_diversity": {"mean": 0.40, "stdev": 0.10, "_placeholder": true, "calibration_due": true, "axis": "simplification", "note": "뉴스는 평서형 단조성이 일부 정상"},
"normalisation_score": {"mean": 0.75, "stdev": 0.12, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "note": "뉴스 장르는 -이다/-한다 비중이 높음"},
"da_streak_rate": {"mean": 1.0, "stdev": 1.0, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "unit": "streaks_per_doc"},
"inanimate_subject_rate": {"mean": 0.18, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T1"},
"by_passive_count": {"mean": 0.8, "stdev": 1.2, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2a", "unit": "per_doc"},
"double_passive_count": {"mean": 0.3, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2b", "unit": "per_doc"},
"pronoun_density": {"mean": 0.015, "stdev": 0.010, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T3"},
"deul_overuse_rate": {"mean": 0.006, "stdev": 0.008, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T4"},
"relative_clause_nesting": {"mean": 0.4, "stdev": 0.6, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T5", "unit": "sentences_per_doc"},
"have_make_literal_count": {"mean": 0.5, "stdev": 0.9, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T6", "unit": "per_doc"},
"double_particle_count": {"mean": 0.4, "stdev": 0.8, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T7", "unit": "per_doc"},
"progressive_aspect_rate": {"mean": 0.08, "stdev": 0.06, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T8b"}
},
"blog": {
"lexical_diversity_ttr": {"mean": 0.60, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"lexical_density": {"mean": 0.27, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"ending_diversity": {"mean": 0.65, "stdev": 0.12, "_placeholder": true, "calibration_due": true, "axis": "simplification", "note": "블로그는 종결 다양성 자연 높음"},
"normalisation_score": {"mean": 0.40, "stdev": 0.18, "_placeholder": true, "calibration_due": true, "axis": "normalisation"},
"da_streak_rate": {"mean": 0.3, "stdev": 0.6, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "unit": "streaks_per_doc"},
"inanimate_subject_rate": {"mean": 0.08, "stdev": 0.06, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T1"},
"by_passive_count": {"mean": 0.3, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2a", "unit": "per_doc"},
"double_passive_count": {"mean": 0.2, "stdev": 0.5, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2b", "unit": "per_doc"},
"pronoun_density": {"mean": 0.018, "stdev": 0.012, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T3", "note": "1인칭 사용 빈도 높음"},
"deul_overuse_rate": {"mean": 0.004, "stdev": 0.007, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T4"},
"relative_clause_nesting": {"mean": 0.2, "stdev": 0.4, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T5", "unit": "sentences_per_doc"},
"have_make_literal_count": {"mean": 0.3, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T6", "unit": "per_doc"},
"double_particle_count": {"mean": 0.2, "stdev": 0.5, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T7", "unit": "per_doc"},
"progressive_aspect_rate": {"mean": 0.12, "stdev": 0.10, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T8b"}
},
"qa": {
"lexical_diversity_ttr": {"mean": 0.58, "stdev": 0.09, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"lexical_density": {"mean": 0.25, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"ending_diversity": {"mean": 0.50, "stdev": 0.13, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"normalisation_score": {"mean": 0.55, "stdev": 0.18, "_placeholder": true, "calibration_due": true, "axis": "normalisation"},
"da_streak_rate": {"mean": 0.5, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "unit": "streaks_per_doc"},
"inanimate_subject_rate": {"mean": 0.15, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T1"},
"by_passive_count": {"mean": 0.4, "stdev": 0.8, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2a", "unit": "per_doc"},
"double_passive_count": {"mean": 0.3, "stdev": 0.6, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2b", "unit": "per_doc"},
"pronoun_density": {"mean": 0.014, "stdev": 0.010, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T3"},
"deul_overuse_rate": {"mean": 0.007, "stdev": 0.010, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T4"},
"relative_clause_nesting": {"mean": 0.25, "stdev": 0.5, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T5", "unit": "sentences_per_doc"},
"have_make_literal_count": {"mean": 0.5, "stdev": 0.9, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T6", "unit": "per_doc"},
"double_particle_count": {"mean": 0.3, "stdev": 0.7, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T7", "unit": "per_doc"},
"progressive_aspect_rate": {"mean": 0.10, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T8b"}
},
"dialogue": {
"lexical_diversity_ttr": {"mean": 0.55, "stdev": 0.10, "_placeholder": true, "calibration_due": true, "axis": "simplification", "note": "대화는 반복이 자연스러움"},
"lexical_density": {"mean": 0.22, "stdev": 0.08, "_placeholder": true, "calibration_due": true, "axis": "simplification"},
"ending_diversity": {"mean": 0.70, "stdev": 0.12, "_placeholder": true, "calibration_due": true, "axis": "simplification", "note": "대화는 종결어미 자연 다양"},
"normalisation_score": {"mean": 0.20, "stdev": 0.15, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "note": "대화는 -한다/-된다/-이다 거의 안 씀"},
"da_streak_rate": {"mean": 0.1, "stdev": 0.3, "_placeholder": true, "calibration_due": true, "axis": "normalisation", "unit": "streaks_per_doc"},
"inanimate_subject_rate": {"mean": 0.05, "stdev": 0.05, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T1"},
"by_passive_count": {"mean": 0.1, "stdev": 0.3, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2a", "unit": "per_doc"},
"double_passive_count": {"mean": 0.1, "stdev": 0.4, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T2b", "unit": "per_doc"},
"pronoun_density": {"mean": 0.020, "stdev": 0.015, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T3"},
"deul_overuse_rate": {"mean": 0.003, "stdev": 0.006, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T4"},
"relative_clause_nesting": {"mean": 0.1, "stdev": 0.3, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T5", "unit": "sentences_per_doc"},
"have_make_literal_count": {"mean": 0.2, "stdev": 0.5, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T6", "unit": "per_doc"},
"double_particle_count": {"mean": 0.1, "stdev": 0.3, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T7", "unit": "per_doc"},
"progressive_aspect_rate": {"mean": 0.15, "stdev": 0.10, "_placeholder": true, "calibration_due": true, "axis": "interference", "type": "T8b"}
}
},
"axis_definitions": {
"simplification": {
"source": "Toral 2019; 보고서 line 351",
"metrics": ["lexical_diversity_ttr", "lexical_density", "ending_diversity"],
"interpretation": "low values → AI-like (repetition, function-word heavy, monotonic endings)"
},
"normalisation": {
"source": "Baker 1993; 보고서 line 352",
"metrics": ["normalisation_score", "da_streak_rate"],
"interpretation": "high values → AI-like (-한다/-된다/-이다 concentration, '-다' streak runs)"
},
"interference": {
"source": "Toury 1995 law of interference; 보고서 line 353",
"metrics": [
"inanimate_subject_rate",
"by_passive_count",
"double_passive_count",
"pronoun_density",
"deul_overuse_rate",
"relative_clause_nesting",
"have_make_literal_count",
"double_particle_count",
"progressive_aspect_rate"
],
"interpretation": "high values → AI-like (영어 통사 보존)"
}
},
"z_score_thresholds": {
"comments": "Phase 6 integrator는 v1.6 thresholds(z>1.0 가산)를 그대로 계승. v2.0 placeholder는 calibration 완료 후 본진 baseline.json에 merge."
}
}
{
"version": "v1.6-2026-05-06",
"source": "KatFish (Park et al., 인간 470 vs LLM 1,624편 / 에세이 771·시 945·초록 378) + LREAD 인간 판독 실험",
"notes": "metric-engineer는 이 baseline을 그대로 import해 z-score 계산에 사용한다. 미공개 셀은 null. 사용자 코퍼스로 보강 시 source에 ',user-corpus-{date}' 추가.",
"genres": {
"essay": {
"comma_inclusion_rate": {"human": 26.31, "ai": 61.03, "ratio": 2.32, "unit": "percent"},
"comma_usage_rate": {"human": 1.13, "ai": 2.56, "ratio": 2.27, "unit": "per_sentence"},
"comma_relative_position": {"human": 0.10, "ai": 0.20, "ratio": 2.00, "unit": "normalized_0to1"},
"comma_segment_length": {"human": 4.35, "ai": 8.56, "ratio": 1.97, "unit": "eojeol_per_segment"},
"comma_pos_diversity": {"human": 24.38, "ai": 59.39, "ratio": 2.44, "unit": "pos_count"},
"ending_comma_rate": {"human": 4.10, "ai": 19.83, "ratio": 4.84, "unit": "percent"}
},
"poetry": {
"comma_inclusion_rate": {"human": 27.01, "ai": 42.90, "ratio": 1.59, "unit": "percent"},
"comma_usage_rate": {"human": 2.61, "ai": 4.84, "ratio": 1.85, "unit": "per_sentence"},
"comma_relative_position": {"human": 0.18, "ai": 0.27, "ratio": 1.50, "unit": "normalized_0to1"},
"comma_segment_length": null,
"comma_pos_diversity": {"human": 23.13, "ai": 23.86, "ratio": 1.03, "unit": "pos_count", "note": "시 장르는 분리도 약함 — 장르 가드 필요"},
"ending_comma_rate": {"human": 4.68, "ai": 15.57, "ratio": 3.33, "unit": "percent"}
},
"abstract": {
"comma_inclusion_rate": {"human": 47.48, "ai": 65.21, "ratio": 1.37, "unit": "percent"},
"comma_usage_rate": {"human": 1.73, "ai": 2.40, "ratio": 1.39, "unit": "per_sentence"},
"comma_relative_position": {"human": 0.15, "ai": 0.24, "ratio": 1.60, "unit": "normalized_0to1", "note": "보고서 본문 추정치(상세 셀 미공개)"},
"comma_segment_length": null,
"comma_pos_diversity": null,
"ending_comma_rate": {"human": 13.27, "ai": 28.01, "ratio": 2.11, "unit": "percent"}
},
"news": null,
"qa": null,
"blog": null
},
"global_average": {
"comma_inclusion_rate": {"human": 33.60, "ai": 56.38, "ratio": 1.68, "unit": "percent"},
"comma_usage_rate": {"human": 1.82, "ai": 3.27, "ratio": 1.79, "unit": "per_sentence"},
"comma_relative_position": {"human": 0.14, "ai": 0.24, "ratio": 1.65, "unit": "normalized_0to1"},
"comma_segment_length": {"human": 5.13, "ai": 7.41, "ratio": 1.45, "unit": "eojeol_per_segment"},
"comma_pos_diversity": {"human": 30.12, "ai": 48.40, "ratio": 1.61, "unit": "pos_count"}
},
"z_score_thresholds": {
"high_risk": 1.0,
"comments": "보고서 §탐지 알고리즘에서 z>1.0 시 가산. 문서별 측정값을 장르 baseline과 비교한 z-score가 1.0 초과면 해당 지표 가산. news/qa/blog는 사용자 코퍼스로 보강 필요. 시 장르는 comma_pos_diversity 분리도가 약하므로 (genre=='poetry') 가드 권장."
},
"lexicons": {
"conclusion_pivot": [
"결론적으로",
"따라서",
"이를 통해",
"그러므로"
],
"safe_balance": [
"양쪽 모두",
"두 가지 모두",
"장점도 있지만",
"신중하게",
"균형"
],
"hanja_nominalizers": [
"성",
"적",
"화"
],
"lexicon_thresholds": {
"conclusion_pivot": {"per_doc_count": 3, "severity": "S1", "merges_into": "D-1"},
"safe_balance": {"per_doc_count": 4, "severity": "S2", "new_code": "G-3"},
"hanja_nominalizers": {"per_doc_density": 12, "severity": "S2", "merges_into": "F-4", "unit": "occurrences_per_doc"}
}
},
"lread_calibration": {
"human_intuition_acc": 0.60,
"human_intuition_p_value": 0.362,
"human_intuition_chance_diff": "no statistical difference",
"rubric_acc": 0.90,
"rubric_fisher_p": 0.015,
"rubric_cohens_h": 0.73,
"ai_essay_false_negative_drop": {
"before": 0.500,
"after": 0.083,
"fisher_p": 0.003
},
"zero_shot_llm_majority_acc": 0.9667,
"comments": "Phase 1 직관 60%는 chance와 통계적 차이 없음(p=.362) — 일반 독자는 AI 한글 식별 어려움. Phase 2 루브릭(쉼표·연결어미·결산·균형 어휘 등 우리 분류 체계와 정렬)을 제공하면 90%로 급상승. v1.6 detector는 LREAD 루브릭의 측정 지표를 그대로 흡수해 인간 판독 90% 수준 도달이 1차 KPI."
},
"v1_6_promotion_targets": {
"promote": [
{"cand_id": "cand-v16-001", "new_code": "C-11", "name": "ending_comma_rate", "severity": "S1", "primary_metric": "ending_comma_rate"},
{"cand_id": "cand-v16-002", "new_code": "C-12", "name": "comma_inclusion_rate", "severity": "S2", "primary_metric": "comma_inclusion_rate"},
{"cand_id": "cand-v16-003", "new_code": "E-5", "name": "comma_segment_length", "severity": "S2", "primary_metric": "comma_segment_length"},
{"cand_id": "cand-v16-004", "new_code": "E-6", "name": "comma_pos_diversity", "severity": "S2", "primary_metric": "comma_pos_diversity", "genre_guard": ["poetry"]},
{"cand_id": "cand-v16-007", "new_code": "G-3", "name": "safe_balance_lexicon", "severity": "S2", "primary_metric": "safe_balance"}
],
"merge": [
{"cand_id": "cand-v16-006", "into": ["D-1", "H-1", "A-2"], "patch": "lexicon 4종 정식 인용 + 임계"},
{"cand_id": "cand-v16-008", "into": ["F-4"], "patch": "hanja_nominalizers 3종 명시 + 한 문서 12회 초과 S2 강화 임계"}
],
"hold": [
{"cand_id": "cand-v16-005", "name": "spacing_regularness", "reason": "보고서 본문에 정량 셀 미공개. 사용자 코퍼스 baseline 확보 후 v1.7 검토. 탐지 전용 신호로만 채용 가능, 윤문 처방 없음(맞춤법 일부러 틀리게 만들지 않음)"},
{"cand_id": "cand-v16-009", "name": "persona_register_mismatch", "reason": "v1.5 monolith fast + author-context 미주입과 충돌. 메타 부스터로만 작동하는 옵트인 설계가 정리되면 v1.7+ 검토"}
]
}
}
"""Humanize KR v2.0 quantitative metrics calculator.
Extends v1.6 metrics.py with post-editese 3축 (simplification·normalisation·
interference) and 8 translation-type detection signals from the Korean
machine-translation/post-editing literature (Toral 2019; Schmaltz 2020;
보고서 T1~T8).
Hard rule: standard library ONLY (json/re/math/collections/os/sys/argparse/
statistics). No konlpy/bareun/mecab/spaCy. Morphological analysis is
approximated with regex + suffix dictionaries (한자어 -성·-적·-화·-도·-력·-감·-원,
평서형 -한다·-된다·-이다, 진행형 -고 있다, 이중 조사 -에서의·-에로의·-으로의·-에의·-으로부터의·-로부터의).
Versioning:
- v1.6 8 functions (comma_inclusion_rate ... lexical_diversity) are imported
*as-is* from references/metrics.py (signature + return preserved). DO NOT
redefine them here. Regression-safe.
- v2.0 adds 14 NEW pure functions for post-editese + T1~T8 detection.
This file lives in `_workspace/v2.0-YYYY-MM-DD/03_metrics/`. Phase 6
integrator will merge it into the project's references/metrics.py.
CLI:
python metrics_v2.py --input run/01_input.txt \
--genre essay --output run/00_metrics_v2.json
"""
from __future__ import annotations
import argparse
import json
import math
import os
import re
import sys
from collections import Counter
from statistics import StatisticsError, mean, pstdev
from typing import Any
# ---------------------------------------------------------------------------
# Import v1.6 metrics module (regression-safe — signatures untouched)
# ---------------------------------------------------------------------------
_HERE = os.path.dirname(os.path.abspath(__file__))
_PROJECT_ROOT = os.path.abspath(os.path.join(_HERE, "..", "..", ".."))
_V1_METRICS_DIR = os.path.join(
_PROJECT_ROOT, ".claude", "skills", "humanize-korean", "references"
)
if _V1_METRICS_DIR not in sys.path:
sys.path.insert(0, _V1_METRICS_DIR)
import metrics as _v1 # noqa: E402 (sys.path mutation is intentional)
# Re-export the 8 v1.6 metric callables verbatim. They keep their original
# signatures and return shapes — `metrics_v2.comma_inclusion_rate(text)`
# is byte-identical to `metrics.comma_inclusion_rate(text)`.
comma_inclusion_rate = _v1.comma_inclusion_rate
comma_usage_rate = _v1.comma_usage_rate
ending_comma_rate = _v1.ending_comma_rate
comma_segment_length = _v1.comma_segment_length
conclusion_pivot_count = _v1.conclusion_pivot_count
safe_balance_count = _v1.safe_balance_count
hanja_nominalizer_density = _v1.hanja_nominalizer_density
lexical_diversity = _v1.lexical_diversity
# Reuse v1.6 internal helpers (private, regression-safe — we never mutate).
_split_sentences = _v1._split_sentences
_eojeols = _v1._eojeols
_strip_punct = _v1._strip_punct
VERSION = "v2.0"
# ---------------------------------------------------------------------------
# v2.0 module-level constants — sufix / lexicon dictionaries
# ---------------------------------------------------------------------------
# 한자어 명사화 접미사 v2.0 확장 — v1.6의 -성·-적·-화 + 보고서 T6 보강 4종.
# token-final 1글자 매칭. 토큰 길이 >= 2 가드는 함수 내부에서.
_HANJA_SUFFIXES_V2 = ("성", "적", "화", "도", "력", "감", "원")
# 평서형 종결 사전 — normalisation 축. 문장 마지막 어절의 어미를 매칭.
# 한자어 + 한다/된다/이다 형태가 가장 흔한 정규화 시그널.
_DECLARATIVE_ENDINGS = ("한다", "된다", "이다")
# 진행형 어미 — T8b. "~고 있다" 표층 매칭. 종결형/연결형 모두 포함.
# 부정형 "있지 않다", 의존명사 "있는" 은 별개. 정규식은 "고 있" 토큰
# 시작점 + 후속 "다/었/는" 등을 폭넓게 캡처.
_PROGRESSIVE_RE = re.compile(r"고\s*있(?:다|었|는|을|던|는다)")
# T2b 이중 피동 표층 어휘. 모두 "되어진/여진/혀진/려진" 등 피동 보조어간 +
# 피동 보조용언 중첩의 표층형. 단순 "되다" 는 정상 표현이므로 제외.
_DOUBLE_PASSIVE_TOKENS = (
"되어진다",
"되어졌다",
"되어진",
"되어지는",
"여지다",
"여진다",
"여졌다",
"여진",
"잊혀진",
"잊혀졌",
"잊혀진다",
"보여진다",
"보여졌다",
"보여진",
"쓰여진다",
"쓰여졌다",
"쓰여진",
"닫혀진",
"열려진",
"불려진",
"놓여진",
)
# T2a "~에 의해 + 피동" — 피동 동사가 직후 N어절 안에 등장해야 매칭.
# 단순 "에 의해" 는 빈번한 자연 한국어이므로 제외 (보고서 T2 caveat).
_BY_PASSIVE_RE = re.compile(
r"에\s*의(?:해|하여)\s+\S{0,12}?(?:되|받|당하|지)(?:다|었|어|ㄴ다|는다|는|ㄹ|을)"
)
# T3 인칭 대명사 — 영어 he/she/it/they 의 1대1 매핑.
# "그" 단독은 지시사·관형사로도 자주 쓰이므로 보수적으로 처리:
# - "그" 뒤에 조사 "는/가/를/의/에게/에서/와/도/만" 이 붙은 경우만 인칭으로 본다.
# - 그녀/그들/그것 은 거의 항상 인칭 대명사이므로 단독 매칭.
_PRONOUN_RE = re.compile(
r"(?:그녀(?:는|가|를|의|에게|와|도|만)?"
r"|그것(?:은|이|을|의|에|에게)?"
r"|그들(?:은|이|을|의|에게|과|도)?"
r"|그(?:는|가|를|의|에게|와|도|만)(?=\s|[\.,!?]|$))"
)
# T4 무정물·추상명사 + -들. 토큰 단위 매칭.
# 보고서 III.3.4.2 + pe_checklist PE5에서 "거의 모두 삭제 후보" 로 거론된
# 핵심 어휘셋. 사전은 보수적(false positive 줄임).
_INANIMATE_DEUL_TOKENS = (
"데이터들",
"정보들",
"결과들",
"연구들",
"아이디어들",
"방법들",
"문제들",
"의견들",
"시스템들",
"기술들",
"사실들",
"사례들",
"이론들",
"개념들",
"현상들",
"특징들",
"요소들",
"원인들",
"영향들",
"변화들",
"기능들",
"조건들",
"기준들",
"관점들",
"원리들",
)
# T6 light verb construction — have/make 류 직역.
# "회의를 가지다·결정을 내리다" 식 light verb.
_HAVE_MAKE_LITERAL_TOKENS = (
"가지고 있다",
"가지고있다",
"가지고 있는",
"가지고있는",
"가지고 있었",
"가지고있었",
"가지고 있으",
"가지고있으",
"갖고 있다",
"갖고있다",
"갖고 있는",
"갖고있는",
"을 가지다",
"를 가지다",
"을 가졌",
"를 가졌",
"을 가진다",
"를 가진다",
"을 만들다",
"를 만들다",
"을 만들었",
"를 만들었",
"을 만들어 낸",
"를 만들어 낸",
"을 만들어낸",
"를 만들어낸",
"회의를 가지",
"회의를 가졌",
"한번 봄을 가지",
"결정을 내리",
"결정을 내렸",
)
# T7 이중 조사 결합. caveat #5 (단순 ~의 제외) 정확히 반영.
# "에서의" 등 6종만 매칭 — 단일 ~의는 절대 매칭 안 됨.
_DOUBLE_PARTICLE_RE = re.compile(
r"(?:에서의|에로의|으로의|에의|으로부터의|로부터의)"
)
# 단락 분리: 빈 줄 1개 이상.
_PARAGRAPH_SPLIT_RE = re.compile(r"\n\s*\n")
# 종결어미 다양성 — 문장 마지막 종결어미 표층(보통 1~2음절 끝마디)을 키로 사용.
# verb stem(예: "결정한다"의 "결정") 부분은 제외하고 어미 부분(예: "한다")만 봐야
# 다양성 신호가 의미를 가진다. 따라서 마지막 2음절을 우선 키로 사용.
_ENDING_FINAL_RE = re.compile(r"([가-힣]{2})[\.!?]\s*$")
# 한 음절만 있는 문장(예: "와.")은 별도로 1음절 매칭.
_ENDING_FINAL_FALLBACK_RE = re.compile(r"([가-힣])[\.!?]\s*$")
# ---------------------------------------------------------------------------
# Local helpers (do not shadow v1.6)
# ---------------------------------------------------------------------------
def _split_paragraphs(text: str) -> list[str]:
text = text.strip()
if not text:
return []
return [p.strip() for p in _PARAGRAPH_SPLIT_RE.split(text) if p.strip()]
def _last_eojeol(sentence: str) -> str:
toks = _eojeols(sentence)
if not toks:
return ""
return _strip_punct(toks[-1])
def _all_tokens(text: str) -> list[str]:
toks = [_strip_punct(t) for t in _eojeols(text)]
return [t for t in toks if t]
# ---------------------------------------------------------------------------
# === v2.0 NEW METRICS ===
# Group A: simplification 축
# ---------------------------------------------------------------------------
def lexical_diversity_ttr(text: str) -> float:
"""Type-token ratio (TTR) over Korean eojeols — simplification axis.
Identical computation to v1.6 ``lexical_diversity`` but exposed under the
Toral 2019 simplification-axis name so the post-editese score can map
cleanly. Returns 0.0 on empty input.
"""
return lexical_diversity(text)
def lexical_density(text: str) -> float:
"""Content-word ratio — proxy for lexical density (simplification axis).
Standard-library proxy: a token is counted as a *content word* if its
final character is one of the v2.0 hanja nominalizer suffixes
(-성·-적·-화·-도·-력·-감·-원), or if it ends with a verb/adjective
declarative marker (-한다·-된다·-이다·-했다·-된다·-였다·-이었다·-답다·-스럽다·-롭다).
Function words (조사·접속부사) are filtered out by length<2 and a small
stopword list.
Returns content_word_count / total_token_count in [0, 1].
"""
tokens = _all_tokens(text)
if not tokens:
return 0.0
stop = {
"그리고", "그러나", "하지만", "또한", "또는", "혹은", "즉", "예를", "예컨대",
"이는", "이것은", "그것은", "그러므로", "따라서",
}
content_suffixes = ("성", "적", "화", "도", "력", "감", "원")
content_endings = (
"한다", "된다", "이다", "했다", "였다", "었다",
"답다", "스럽다", "롭다", "하다", "되다",
)
hits = 0
for t in tokens:
if len(t) < 2:
continue
if t in stop:
continue
if t[-1] in content_suffixes:
hits += 1
continue
if any(t.endswith(end) for end in content_endings):
hits += 1
return hits / len(tokens)
def ending_diversity(text: str) -> float:
"""Sentence-ending diversity — unique endings / total sentences.
Approximates 종결어미 다양성. Sentence is split via v1.6 helper; the
last 1~3 syllables (Hangul only) before the terminal punctuation are
used as the ending key. Higher = more diverse (more human-like).
Returns 0.0 when no sentence ends with valid punctuation.
"""
sents = _split_sentences(text)
keys: list[str] = []
for s in sents:
m = _ENDING_FINAL_RE.search(s)
if m:
keys.append(m.group(1))
continue
m2 = _ENDING_FINAL_FALLBACK_RE.search(s)
if m2:
keys.append(m2.group(1))
if not keys:
return 0.0
return len(set(keys)) / len(keys)
# ---------------------------------------------------------------------------
# Group B: normalisation 축
# ---------------------------------------------------------------------------
def normalisation_score(text: str) -> float:
"""Declarative-form (~한다/~된다/~이다) concentration — normalisation axis.
Returns the ratio of sentences whose final eojeol ends with one of the
three canonical declarative markers (~한다·~된다·~이다 — variants
`-한다.`, `-한다!` 등은 punctuation-stripped). High values (>0.7) signal
normalised, AI-like prose; very low values (<0.3) often signal informal
speech (해체) or heterogeneous registers. Range [0, 1].
"""
sents = _split_sentences(text)
if not sents:
return 0.0
hits = 0
for s in sents:
last = _last_eojeol(s)
if not last:
continue
for ending in _DECLARATIVE_ENDINGS:
if last.endswith(ending):
hits += 1
break
return hits / len(sents)
def da_streak_rate(text: str) -> int:
"""Count of '-다' streak runs of length >= 4 — T8a normalisation signal.
A *streak* = consecutive sentences whose final eojeol ends in '다'
(any '~다' — 한다·된다·이다·었다·았다·였다 등). Streaks of length 4+
are reported. The return value is the number of distinct streaks
(not the total streak length). Documents with one long uniform run
of '-다' will return 1; truly diverse docs return 0.
"""
sents = _split_sentences(text)
streaks = 0
cur = 0
for s in sents:
last = _last_eojeol(s)
if last.endswith("다"):
cur += 1
else:
if cur >= 4:
streaks += 1
cur = 0
if cur >= 4:
streaks += 1
return streaks
# ---------------------------------------------------------------------------
# Group C: interference 축 — T1~T8 detection signals
# ---------------------------------------------------------------------------
def inanimate_subject_rate(text: str) -> float:
"""T1: inanimate-subject + universal-verb pattern rate.
Approximation: count sentences whose first content noun ends with one
of the v2.0 hanja suffixes (-성·-적·-화·-도·-력·-감·-원) OR matches a
short list of inanimate/abstract subjects (`연구·데이터·분석·결과·시스템·
기술·사례·현상·이론·정책·보고서`) AND whose verb is a universal
cognitive/declarative verb (보여준다·시사한다·만든다·드러낸다·제시한다·
나타낸다·증명한다·말해준다·의미한다·가져온다). Returns
matching_sents / total_sents in [0, 1].
"""
sents = _split_sentences(text)
if not sents:
return 0.0
inanimate_subjects = (
"연구", "데이터", "분석", "결과", "시스템", "기술", "사례",
"현상", "이론", "정책", "보고서", "AI", "인공지능", "모델",
"알고리즘", "변화", "위기", "혁신", "사회", "경제",
)
universal_verbs = (
"보여준다", "보여줬다", "보여주는", "시사한다", "시사하는",
"만든다", "만들어", "드러낸다", "드러냈다", "드러내는",
"제시한다", "제시했다", "나타낸다", "나타냈다", "나타내는",
"증명한다", "증명했다", "말해준다", "말해주는",
"의미한다", "의미하는", "가져온다", "가져왔다", "가져오는",
)
hits = 0
for s in sents:
toks = _all_tokens(s)
if not toks:
continue
head = toks[0]
# Subject heuristic: first token, optionally followed by 은/는/이/가.
head_stem = head
for josa in ("은", "는", "이", "가", "도"):
if head.endswith(josa) and len(head) > 1:
head_stem = head[:-1]
break
is_inanimate = (
head_stem in inanimate_subjects
or (len(head_stem) >= 2 and head_stem[-1] in _HANJA_SUFFIXES_V2)
)
if not is_inanimate:
continue
# Verb heuristic: any later token in `universal_verbs`.
if any(any(uv in t for uv in universal_verbs) for t in toks[1:]):
hits += 1
return hits / len(sents)
def by_passive_count(text: str) -> int:
"""T2a: ~에 의해 + passive-verb co-occurrence count.
Bare '에 의해' is excluded. Only the regex-anchored
'에 의해 ... 되/받/당하/지' pattern is counted. Returns int >= 0.
"""
if not text.strip():
return 0
return len(_BY_PASSIVE_RE.findall(text))
def double_passive_count(text: str) -> int:
"""T2b: double-passive (잊혀지다·보여지다·되어진다·여지다·쓰여지다 …) count.
Surface-form lexicon. 단순 '되다' 는 제외 (자연 표현). Returns int >= 0.
"""
if not text.strip():
return 0
n = 0
for tok in _DOUBLE_PASSIVE_TOKENS:
n += text.count(tok)
return n
def pronoun_density(text: str) -> float:
"""T3: personal-pronoun density per paragraph (avg).
Counts 그/그녀/그것/그들 (+ 조사 fused forms). Bare '그' is only counted
when followed by 는/가/를/의/에게/와/도/만 to filter out demonstrative use.
Returns paragraph-mean of (pronoun_tokens / paragraph_eojeols).
Range [0, 1]. Empty input returns 0.0.
"""
paragraphs = _split_paragraphs(text)
if not paragraphs:
return 0.0
densities: list[float] = []
for p in paragraphs:
toks = _all_tokens(p)
if not toks:
continue
pronoun_hits = len(_PRONOUN_RE.findall(p))
densities.append(pronoun_hits / len(toks))
if not densities:
return 0.0
try:
return mean(densities)
except StatisticsError:
return 0.0
def deul_overuse_rate(text: str) -> float:
"""T4: inanimate / abstract noun + '-들' over-use ratio.
Returns deul_overuse_hits / total_eojeols. The numerator counts
occurrences of any token in `_INANIMATE_DEUL_TOKENS` (데이터들·정보들·
결과들·연구들·아이디어들·방법들·문제들·의견들·시스템들·기술들 …).
Range [0, 1] — practical AI text seldom exceeds ~0.05.
"""
toks = _all_tokens(text)
if not toks:
return 0.0
hits = 0
for t in toks:
# Match exact OR with one short josa suffix (-과/와/이/가/을/를/의/에/은/는/도)
if t in _INANIMATE_DEUL_TOKENS:
hits += 1
continue
for base in _INANIMATE_DEUL_TOKENS:
if t.startswith(base) and len(t) - len(base) in (1, 2):
# remaining tail must be hangul (likely josa)
tail = t[len(base):]
if all("가" <= ch <= "힣" for ch in tail):
hits += 1
break
return hits / len(toks)
def relative_clause_nesting(text: str) -> int:
"""T5: count of sentences with relative-clause nesting depth >= 3.
Approximation: a sentence is nested when it contains 3+ adnominal
clause endings -ㄴ/-는/-ㄹ/-한/-된/-할 followed by a noun (heuristic:
the syllable before whitespace). We check every sentence for the
count of token endings in `(ㄴ|는|ㄹ|던|할|한|된|될)` followed by a
short space-separated noun. Returns the *number of sentences*
(not total nestings) with depth >= 3.
"""
sents = _split_sentences(text)
if not sents:
return 0
# 관형형 어미 종결 음절 매칭 — 어절 끝이 (ㄴ|는|ㄹ|던|한|된|할|될|온) 인 토큰 수.
adnominal_re = re.compile(r"[가-힣]+(?:ㄴ|는|ㄹ|던|한|된|할|될|온|간)\s+[가-힣]")
matches_per_sent = []
for s in sents:
m = adnominal_re.findall(s)
matches_per_sent.append(len(m))
return sum(1 for c in matches_per_sent if c >= 3)
def have_make_literal_count(text: str) -> int:
"""T6: count of literal have/make light-verb constructions.
가지고 있다·갖고 있다·~을 가지다·~을 만들다·회의를 가지다·결정을 내리다 …
Returns int >= 0.
"""
if not text.strip():
return 0
n = 0
for tok in _HAVE_MAKE_LITERAL_TOKENS:
n += text.count(tok)
return n
def double_particle_count(text: str) -> int:
"""T7: double-particle (에서의·에로의·으로의·에의·으로부터의·로부터의) count.
Caveat #5 (single ~의 excluded) is *enforced by construction* — the
regex never matches a bare ~의. Returns int >= 0.
"""
if not text.strip():
return 0
return len(_DOUBLE_PARTICLE_RE.findall(text))
def progressive_aspect_rate(text: str) -> float:
"""T8b: progressive aspect '~고 있다' rate per sentence.
Returns progressive_hits / total_sentences. Surface-form match; not
every '~고 있다' is reducible (예: 진행 의미가 본질적인 동사) but
high rates flag automatic 1대1 매핑. Range typically [0, 1+] — values
>0.5 signal heavy literal mapping.
"""
sents = _split_sentences(text)
if not sents:
return 0.0
hits = sum(len(_PROGRESSIVE_RE.findall(s)) for s in sents)
return hits / len(sents)
# ---------------------------------------------------------------------------
# === v2.0 INTERFERENCE INDEX ===
# Composite signal weighted across T1~T8.
# ---------------------------------------------------------------------------
def interference_index(text: str) -> dict[str, Any]:
"""T1~T8 weighted interference signal — interference axis composite.
Returns a dict with each sub-signal score plus a `weighted_total`
that sums per-type contributions (each capped to [0, 1] by simple
rescaling). This is descriptive, not a z-score — calibration to
baseline happens in compute_all_v2.
"""
n_sents = max(len(_split_sentences(text)), 1)
chars = max(len(text), 1)
components = {
"T1_inanimate_subject_rate": inanimate_subject_rate(text),
"T2a_by_passive_per_1k": by_passive_count(text) / chars * 1000,
"T2b_double_passive_per_1k": double_passive_count(text) / chars * 1000,
"T3_pronoun_density": pronoun_density(text),
"T4_deul_overuse_rate": deul_overuse_rate(text),
"T5_nested_clause_count": relative_clause_nesting(text),
"T6_have_make_per_1k": have_make_literal_count(text) / chars * 1000,
"T7_double_particle_per_1k": double_particle_count(text) / chars * 1000,
"T8b_progressive_rate": progressive_aspect_rate(text),
}
# Each component clamped to [0, 1] heuristically:
weights = {
"T1_inanimate_subject_rate": 1.0, # already in [0,1]
"T2a_by_passive_per_1k": 0.2, # /5
"T2b_double_passive_per_1k": 0.2,
"T3_pronoun_density": 4.0, # human <0.015, scale up
"T4_deul_overuse_rate": 4.0,
"T5_nested_clause_count": 0.05, # /20
"T6_have_make_per_1k": 0.2,
"T7_double_particle_per_1k": 0.5,
"T8b_progressive_rate": 1.0,
}
weighted_total = 0.0
for k, v in components.items():
weighted_total += min(1.0, max(0.0, v * weights[k]))
return {
"components": components,
"weighted_total": weighted_total,
"n_sentences": n_sents,
"n_chars": chars,
}
# ---------------------------------------------------------------------------
# Baseline + z-score (v2.0 extension)
# ---------------------------------------------------------------------------
def _default_baseline_v2_path() -> str:
return os.path.join(_HERE, "baseline_v2_diff.json")
def _load_baseline_v2(path: str | None) -> dict[str, Any]:
p = path or _default_baseline_v2_path()
if not os.path.exists(p):
return {}
with open(p, "r", encoding="utf-8") as f:
return json.load(f)
def _z_simple(value: float, mean_v: float, stdev: float) -> float | None:
if stdev is None or stdev <= 0:
return None
return (value - mean_v) / stdev
# ---------------------------------------------------------------------------
# Public entry point — v2.0 superset
# ---------------------------------------------------------------------------
def compute_all_v2(
text: str,
genre: str = "essay",
baseline_path: str | None = None,
baseline_v2_path: str | None = None,
) -> dict[str, Any]:
"""Compute v1.6 metrics + v2.0 post-editese + T1~T8 signals.
Returns the v1.6 ``compute_all`` payload extended with:
- ``v2_metrics``: dict of new metric values
- ``v2_z_scores``: per-metric z against baseline_v2 (None if placeholder)
- ``v2_baseline_warnings``: list of metric keys whose baseline cell
carries `_placeholder: true`.
"""
base = _v1.compute_all(text, genre=genre, baseline_path=baseline_path)
v2_metrics: dict[str, float | int] = {
"lexical_diversity_ttr": lexical_diversity_ttr(text),
"lexical_density": lexical_density(text),
"ending_diversity": ending_diversity(text),
"normalisation_score": normalisation_score(text),
"da_streak_rate": da_streak_rate(text),
"inanimate_subject_rate": inanimate_subject_rate(text),
"by_passive_count": by_passive_count(text),
"double_passive_count": double_passive_count(text),
"pronoun_density": pronoun_density(text),
"deul_overuse_rate": deul_overuse_rate(text),
"relative_clause_nesting": relative_clause_nesting(text),
"have_make_literal_count": have_make_literal_count(text),
"double_particle_count": double_particle_count(text),
"progressive_aspect_rate": progressive_aspect_rate(text),
}
interference = interference_index(text)
bv2 = _load_baseline_v2(baseline_v2_path)
cells = {}
warnings: list[str] = []
if bv2:
genres = bv2.get("genres", {}) or {}
cells = genres.get(genre) or genres.get("essay") or {}
z_scores: dict[str, float | None] = {}
for k, v in v2_metrics.items():
cell = cells.get(k)
if not cell:
z_scores[k] = None
continue
if cell.get("_placeholder"):
warnings.append(k)
z_scores[k] = _z_simple(
float(v), float(cell.get("mean", 0.0)), float(cell.get("stdev", 0.0))
)
base["version"] = VERSION
base["v2_metrics"] = v2_metrics
base["v2_interference_index"] = interference
base["v2_z_scores"] = z_scores
base["v2_baseline_warnings"] = warnings
return base
# ---------------------------------------------------------------------------
# CLI
# ---------------------------------------------------------------------------
def _main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Humanize KR v2.0 metric runner")
parser.add_argument("--input", required=True, help="Input text file path")
parser.add_argument("--genre", default="essay", help="essay/news/blog/qa/dialogue")
parser.add_argument("--output", default=None, help="Output JSON path (optional)")
parser.add_argument(
"--baseline", default=None, help="Override v1.6 baseline JSON path"
)
parser.add_argument(
"--baseline-v2", default=None, help="Override v2.0 baseline JSON path"
)
args = parser.parse_args(argv)
with open(args.input, "r", encoding="utf-8") as f:
text = f.read()
result = compute_all_v2(
text,
genre=args.genre,
baseline_path=args.baseline,
baseline_v2_path=args.baseline_v2,
)
if args.output:
os.makedirs(os.path.dirname(os.path.abspath(args.output)), exist_ok=True)
with open(args.output, "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=2)
print(result["risk_band"])
return 0
# ---------------------------------------------------------------------------
# v1.6 호환 별칭 (prepare_monolith_input.py가 _metrics_mod.compute_all 호출)
# ---------------------------------------------------------------------------
compute_all = compute_all_v2 # v2.0 출력은 v1.6의 상위집합 (integration_note §1)
if __name__ == "__main__":
sys.exit(_main())
Quick Rules — Monolith Fast Path 전용 (v2.0)
humanize-monolith 에이전트가 한 콜에서 탐지·윤문·자체검증을 끝내기 위해 사용하는 슬림 룰북. 본진 ai-tell-taxonomy.md(590줄)에서 S1·S2 핵심 패턴만 추려 처방과 함께 한 줄로 압축했다.
원칙: 정의 1줄 + 처방 1줄. 예문 생략. 본진 ID와 1:1 매칭.
Do-NOT (탐지·윤문 모두 제외): 고유명사·제품명·모델명·기관명, 수치·날짜·단위, 큰따옴표 안 직접 인용, 법률 조문, 수학·화학·통계 표기, 영어 약어(LLM·GPU·MCP·API 등 업계 표준).
과윤문 가드: 변경률 30% 초과 = 경고, 50% 초과 = 강제 중단·롤백.
---
A. 번역투 (Translation-ese)
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| A-1 | "~에 대해(서)" | S1 | 목적격 조사로 직결("X에 대해 논의" → "X를 논의") |
| A-2 | "~를 통해/통하여" 남발 | S1 | "~로", "~해서", "~함으로써"로 분산 |
| A-3 | "~에 있어(서)" | S1 | "~에서", "~을 볼 때" |
| A-4 | "~라는 점에서" 3회+ | S2 | "~서", "~라는 이유로" |
| A-5 | "~와 관련하여/관련된" | S2 | "~에", "~의" |
| A-6 | "~에 기반하여/바탕으로" 남발 | S2 | "~로", "~을 보고" |
| A-7 | "가지고 있다" / have·make·take·give + N 직역 | S1 | 형용사·동사 환원 또는 이중주어("회의를 가지다" → "회의를 했다", "강한 경쟁력을 가지고 있다" → "경쟁력이 강하다") |
| A-8 | 이중 피동 "~되어진다" | S1 | 능동 또는 단일 피동 ("판단되어진다" → "판단된다") |
| A-9 | "~에 의해" 피동 | S2 | 행위자를 주어로("AI에 의해 생성" → "AI가 만든") |
| A-10 | "~할 수 있다" 남발 | S2 | 단언으로("높일 수 있다" → "높인다") |
| A-11 | "~을 위해" 목적절 남발 | S2 | "~려고", "~위한" |
| A-15 | 추상 주어 + 만능 동사 / 사역·인지 동사 | S2 | 구체 주어로 환원, 사역은 "X 때문에/덕분에/로 인해" 부사절, 인지 동사(suggest/show/indicate/reveal)는 "~에 따르면 ~이다"·"~으로 ~이 드러났다" 분리 |
| A-16 | "그/그녀/그것/그들" 단락 ≥3회 영어 대명사 직역 | S1 | 50%+ 영형(생략) 또는 호칭·명사구로 (김도훈 2009) |
| A-18 | 명사 앞 ≥3어절 관형구·관계절 좌향 수식 | S2 | 문장 분리 또는 후치 동격절("X를 만났는데, 그 X는 …") (박옥수 2018) |
| A-19 | 이중 조사 "~에서의/~에로의/~으로의/~에의/~으로부터의" | S2 | 절·구로 풀어쓰기. 단순 ~의는 비대상 (김정우 2007) |
B. 영어 인용·용어 과다
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| B-1 | 한글 + 괄호 영어 매번 ("~(Sovereign AI)" 처럼) | S2 | 첫 등장만 병기, 이후 한글만 |
| B-2 | 영어 어휘 직역 가능한데 그대로 | S2 | 한국어로 옮기되 업계 표준은 유지 |
C. 구조적 AI 패턴
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| C-5 | 이모지 남발 | S1 | 장르 칼럼·리포트면 전부 삭제 |
| C-7 | "먼저·반면·결국" 3단 공식 | S2 | 접속사 1~2개로 줄이거나 본문에 녹여 제거 |
| C-8 | "A인가·B인가" 대구 반복 | S2 | 한 번만 살리고 나머지는 평서문으로 |
| C-9 | 숫자 괄호 인덱싱 "(1)·(2)·(3)" | S2 | 본문에 녹이거나 단순 줄바꿈 |
| C-10 | 콜론 부제 헤딩 "X: Y" 반복 | S1 | 헤딩 짧게 또는 평서 헤딩으로 |
| C-11 | 연결어미 뒤 쉼표 (-고/-며/-지만/-며서/-아서/-어서 직후 쉼표) | S1 | 쉼표 제거. 6+회=강한 신호. KatFish 4.84배 분리도 |
D. AI 특유의 관용구 (Signature Phrases)
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| D-1 | 결산 피벗 lexicon "결론적으로/따라서/이를 통해/그러므로/요약하면/정리하면" | S1 | 3회 초과 시 1~2건 다른 종결로 치환, 나머지 삭제 |
| D-2 | "시사하는 바가 크다/주목할 만하다" | S1 | 삭제 또는 구체 결론으로 |
| D-3 | "본질적으로/핵심적으로" | S1 | 삭제 |
| D-4 | hype 어휘(파격적·압도적·강력한·획기적·치명적) 3회+ | S1 | 구체 수치·사실로 환원 |
| D-5 | 의인화 추상 주어("기술이 묻는다·시대가 부른다") | S1 | 사람·기관 주어로 |
| D-6 | 결말 공식 "~할 때다/~해야 한다/~지금이야말로" | S1 | 평서로 닫거나 삭제 |
| D-7 | 변환 공식 "X에서 Y로" 반복 | S2 | 한 번만, 나머지는 일반 서술 |
E. 리듬·종결어미
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| E-1 | 문장 길이 균일(stdev 8 미만) | S2 | 단문 1~2개 / 장문 1개를 각 문단에 의도적 삽입 |
| E-2 | 동일 종결어미 "~다" 4문장 연속 + 진행형 "~고 있다" 자동 매핑 | S2 | "~었다·~ㄴ다·~는다·~기 마련이다·~ㄹ 것이다" 등 다양화. "~고 있다" 단순 시제 환원 가능 시 환원("읽고 있다" → "읽는다") |
| E-7 | 청자 경어법 4단계(해라/하게/하오/해요/합쇼) 일관성 손실 (대화·구어 한정) | S2 | 한 단락 내 혼용 금지, 격식 일관 (김혜영 2019, estimated) |
F. 과도한 수식·중복
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| F-4 | 한자어 명사화 -성/-적/-화 + 영어 명사화 -tion/-ment/-ness/-ity 누적 (한 글 12회+) | S2 | 동사·형용사 어근으로 환원("the implementation of the policy" → "정책 시행" 또는 "정책을 시행하기") |
| F-5 | "~적 N" 추상 체인 ("전략적 함의·실천적 기반") | S2 | 명사+명사 또는 풀어쓰기("전략 함의·실천의 기반") |
G. Hedging
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| G-1 | "~것이다/~할 것이다" 미래 단정 남발 | S2 | 현재형·확정형으로 |
| G-2 | "~로 보인다/~인 듯하다" 추정 남발 | S2 | 단언 가능한 곳은 단언 |
| G-3 | 안전 균형 lexicon "양쪽 모두/두 가지 모두/장점도 있지만/신중하게/균형" | S2 | 4회 초과 시 1~2건 화자 입장으로 치환 |
H. 접속사 남발
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| H-1 | 문두 접속사 "또한·따라서·즉·나아가·아울러·게다가·더욱이" 5회+ | S1 | 대량 제거. 문장 자체가 흐름을 잡게 |
| H-3 | 메타 진입 "이는·이 점에서·이 관점에서·이 말은" 3회+ | S1 | 본문에 녹이거나 삭제 |
| H-4 | "즉" 남발 | S2 | 1회로 제한 |
I. 형식명사·의존명사
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| I-1 | "~인 것이다/~한 것이다" 결말 | S1 | 평서형으로 |
| I-2 | "X은 ~라는 점에 있다" | S2 | "X는 ~다" 직설로 |
| I-3 | "~다는 뜻이다/~다는 의미다" 결말 | S2 | 본문에 풀어 쓰기 |
| I-4 | 권고형 결말 "~해야 한다·~합니다" 반복 | S2 | 평서·단언으로 |
J. 시각 장식
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| J-1 | 헤딩 마크다운 ** 강조 남발 | S2 | 칼럼·리포트면 거의 다 제거 |
| J-2 | 따옴표 강조 5회+ | S1 | 핵심 한두 개만 살리고 평어로 |
| J-3 | 불릿 리스트 (장르가 칼럼·리포트일 때) | S2 | 문단 산문으로 통합 |
---
자체검증 체크리스트 (monolith 윤문 후 자가 점검)
윤문 직후 5초 내에 다음을 자체 점검한다. 한 항목이라도 위반이면 해당 edit 롤백.
1. 고유명사·수치·날짜·인용 100% 보존: 원문 대비 한 글자도 다르지 않은가 2. 변경률: 30% 이하인가 (50% 초과는 작업 중단) 3. 장르 이탈 없음: 칼럼이 에세이·문학으로 변하지 않았는가, 리포트가 블로그체로 떨어지지 않았는가 4. register 보존: 원문 격식체면 결과도 격식체. 평어체로 떨어뜨리지 않는다 5. 잔존 S1 패턴 0건: D-1~D-7, A-7, A-8, A-16, C-5, C-10, C-11, H-1, I-1, J-2 핵심 S1이 남아있지 않은가 6. 인공 표현 자제: 원문에 없던 비유·수사·문학적 표현을 윤문 과정에서 임의로 추가하지 않았는가
위반 시: edit 롤백 → 다시 윤문 → 재점검. 자체 루프 최대 1회. 이상 미해결이면 결과를 그대로 출력하되 summary.md에 "자가검증 미통과 항목 N건" 표기.
등급 기준 (자가 채점)
- A: S1 잔존 0, S2 잔존 2 이하, 변경률 10~25%, 자체검증 6항 모두 통과
- B: S1 잔존 0, S2 잔존 4 이하, 자체검증 5항 이상 통과
- C: S1 잔존 1~2 또는 자체검증 4항 이하 통과 — 사용자에게 strict 모드 권고
- D: S1 잔존 3+ 또는 변경률 50% 초과 — 작업 중단 권고
v2.0 신규/보강은 A-7·A-15·A-16·A-18·A-19·E-2·E-7·F-4 8건 (A-17 hold). 학술 인용 전문은 references/scholarship.md. post-editese 3축 metric은 본 룰북 미반영(metric only 트랙). A-17 무정물·추상명사 '-들'은 학술 anchor(전영철 2007·곽은주·진실로 2011) 강하나 외부 회차(2026-05-07 위키 6편)에서 양성 0건 — NMT 원본 출력 회차 후 v2.1에서 동일 ID로 재평가.