feat: install korean technical blog skill bundle

.agents/skills의 technical-document-author,
revising-korean-technical-prose, writing-natural-korean을
korean-technical-blog-skills-bundle-v1의 세 스킬로 교체한다.

- writing-korean-technical-blogs: 문제·제약·선택·구현·결과·한계 구조화
- reducing-ai-like-korean-writing: 상투성·추상화·반복 제거
- editing-korean-grammar-and-expression: 맞춤법·띄어쓰기·호응 검수

상류를 수정하지 않고 복사했다. diff -r 0건, MANIFEST.sha256 검증 통과,
번들 validate_skill.py 3/3 PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-07 14:20:42 +09:00
co-authored by Claude Opus 5
parent 1099834617
commit 25644cc4d9
81 changed files with 5261 additions and 1484 deletions
@@ -0,0 +1,44 @@
# editing-korean-grammar-and-expression
한국어 맞춤법·띄어쓰기·문법·높임·표현을 보수적으로 교정하는 Agent Skill 패키지다. 의미, 수치, 코드, URL, 고유 명칭, 허용 표현과 의도적인 말투를 우선 보존한다.
## 구성
```text
editing-korean-grammar-and-expression/
├── SKILL.md
├── README.md
├── references/
│ ├── decision-policy.md
│ ├── output-modes.md
│ ├── rule-catalog.md
│ └── source-basis.md
├── scripts/
│ └── validate_skill.py
└── tests/
├── cases.json
├── evaluation-rubric.md
└── pressure-scenarios.md
```
## 사용 예
```text
이 문서를 원래 말투와 기술 용어를 유지하면서 한국어 문법·표현만 윤문해 주세요.
```
```text
다음 발표 대본을 preserve-style 모드로 교정하고, 확정 오류만 설명해 주세요.
```
```text
다음 문장을 teaching 모드로 교정해 주세요. 혼동하기 쉬운 반례도 함께 설명하세요.
```
## 검증
```bash
python scripts/validate_skill.py
```
실제 에이전트 행동 검증은 `tests/pressure-scenarios.md``tests/cases.json`을 스킬 전후 조건에서 실행한다.
@@ -0,0 +1,85 @@
---
name: editing-korean-grammar-and-expression
description: Use when revising Korean text that may contain spelling, spacing, grammar, honorific, register, or expression problems, especially when meaning, formatting, terminology, code, quotations, and intentional voice must remain unchanged.
---
# 한국어 문법·표현 윤문
## 개요
한국어 문장을 **보수적으로 교정하고 필요한 범위만 윤문**한다. 핵심 원칙은 다음과 같다.
> 맞는 표현을 틀렸다고 바꾸지 않는다. 의미·사실·문체를 바꿀 위험이 있으면 수정하지 않고 보류한다.
이 스킬은 표준어 기반의 일반 한국어를 기본 대상으로 한다. 맞춤법·띄어쓰기·문법 오류는 교정하지만, 자연스러움·간결성·문체 취향은 사용자가 요청하지 않는 한 제안으로만 다룬다.
## 기본 입력
가능하면 다음 정보를 사용한다. 없으면 문맥에서 추론하되, 교정을 막는 중의성이 있을 때만 경고한다.
- 원문
- 목적: 교정, 윤문, 표준화, 학습용 설명
- 문서 유형과 독자
- 보존할 용어·고유 명칭·말투
- 출력 모드
## 필수 절차
1. **범위 결정:** 강제 규범 교정과 선택적 문체 개선을 분리한다.
2. **보호 구간 식별:** 코드, URL, 전자 우편, 경로, 명령어, 식별자, 직접 인용, 사용자가 잠근 구간을 읽기 전용으로 둔다.
3. **문맥 판정:** 표면 문자열만 보지 말고 품사·뜻·앞뒤 문장을 함께 본다.
4. **최소 수정:** 같은 정확성을 얻을 수 있다면 공백 수정, 한 어절 수정, 문장 재작성 순으로 선호한다.
5. **불변식 검증:** 부정, 조건, 시제, 양태, 수치, 고유 명칭, 기술 용어, 높임 등급, 마크다운 구조가 유지됐는지 확인한다.
6. **보류:** 복수 해석이 남거나 전문 용어·고유 명칭 가능성이 있으면 원문을 유지하고 경고한다.
## 판정 기준
| 등급 | 조건 | 처리 |
|---|---|---|
| A | 공식 규범을 직접 적용할 수 있고 해석이 하나임 | 자동 교정 |
| B | 품사·뜻·문맥이 일치하고 경쟁 분석이 없음 | 자동 교정 + 필요 시 근거 |
| C | 한 해석이 우세하지만 다른 해석도 가능함 | 제안 |
| D | 의미·지시 대상·전문 용어 여부가 불명확함 | 보류 또는 질문 |
| E | 보호 구간·의도적 문체·허용형임 | 유지 |
세부 우선순위와 충돌 규칙은 `references/decision-policy.md`를 따른다. 띄어쓰기·활용·높임 등의 최소 대조 사례는 `references/rule-catalog.md`를 필요할 때만 읽는다.
## 절대 규칙
- 원문에 없는 사실·효용·감정·인과관계를 추가하지 않는다.
- 가능성을 확정으로, 권고를 의무로, 일부를 전체로 강화하지 않는다.
- 조사·의존 명사·어미가 갈릴 수 있는 표현을 일괄 치환하지 않는다.
- 규범상 허용되는 표현을 오류로 표시하거나 한 형태로 강제 통일하지 않는다.
- 방언·신조어·캐릭터 말투는 표준화 요청이 없으면 보존한다.
- 근거 없이 “더 자연스럽다”, “보통 이렇게 쓴다”라고 단정하지 않는다.
## 출력
기본값은 `brief`다. 교정문을 먼저 제시하고, 의미 있는 수정과 경고만 짧게 덧붙인다. 사용자가 결과만 요구하면 `silent`, 학습을 원하면 `teaching`, 중의성이 핵심이면 `review`를 사용한다. 형식은 `references/output-modes.md`를 따른다.
## 대표 예시
**입력**
> 문서의 `할수있다` 필드는 변경하지 말고, 이 일은 할수있다. 비가 올듯하다.
**교정**
> 문서의 `할수있다` 필드는 변경하지 말고, 이 일은 할 수 있다. 비가 올듯하다.
- 인라인 코드는 보호한다.
- 일반 문장의 의존 명사 `수`는 띄어 쓴다.
- `올듯하다`는 허용형이므로 오류로 고치지 않는다.
## 흔한 실패
| 실패 | 올바른 대응 |
|---|---|
| 모든 `뿐·만큼·대로·지`를 같은 방식으로 띄움 | 품사와 의미를 먼저 판정 |
| 한 오류 때문에 문단 전체를 다시 씀 | 오류 범위만 최소 수정 |
| 허용형을 선호형으로 강제 변경 | 맞는 입력은 유지 |
| 윤문하면서 단정 강도나 주체를 변경 | 원문의 명제와 양태 보존 |
| 코드·URL·제품명 내부를 교정 | 보호 구간으로 제외 |
| 문맥이 부족한데 확신하는 설명을 생성 | 원문 유지 + 경고 |
배포 전에는 `tests/cases.json``tests/evaluation-rubric.md`로 회귀 검증한다.
@@ -0,0 +1,111 @@
# 판정·보존 정책
## 1. 기본 정책
- 기본 언어 변종: 표준어
- 기본 문체: 원문 보존
- 기본 교정 성향: 보수적
- 생성 기본값: 원칙형 우선
- 입력이 이미 허용형이면: 유지
- 해결되지 않은 중의성: 자동 수정 금지
- 선택적 자연스러움 개선: 제안으로 분리
오류를 하나 놓치는 것보다 올바른 표현을 잘못 고치거나 의미를 바꾸는 위험을 더 크게 본다.
## 2. 우선순위
아래 순서에서 상위 항목은 항상 하위 항목을 제약한다.
1. 사용자 잠금과 보호 구간
2. 의미·사실·데이터 보존
3. 공식적으로 확정 가능한 강제 규범
4. 사전의 품사·뜻·단어 판정
5. 통사·의미 문맥
6. 높임·문체 일관성
7. 자연스러움·간결성
8. 취향 기반 재작성
하위 규칙이 상위 규칙과 충돌하면 하위 수정을 취소하고 원문을 유지하거나 `review`로 보낸다.
## 3. 반드시 보존할 불변식
- 명제적 의미
- 긍정과 부정
- 조건과 예외
- 시제와 시간 관계
- 가능성·의무·권고·추정 등 양태
- 주체·객체·지시 대상
- 인명·지명·기관명·제품명
- 숫자·날짜·단위·버전
- 기술 용어와 사용자가 지정한 표기
- 인용문과 발화자의 의도
- 목록, 표, 제목, 링크 등 마크다운 구조
- 화자의 높임 등급과 의도적인 구어체
## 4. 보호 구간
다음 구간은 기본적으로 읽기 전용이다.
```text
fenced_code
inline_code
url
email
file_path
shell_command
identifier
quoted_verbatim
user_locked_span
```
마크다운 파서나 구문 정보를 우선하며 정규식은 후보 탐지에만 쓴다. 보호 구간 안에서 맞춤법 오류처럼 보이는 문자열도 바꾸지 않는다.
## 5. 자동 교정 금지 조건
다음 조건 중 하나라도 충족하면 자동 수정하지 않는다.
- 품사에 따라 답이 달라지는 표현인데 문맥이 부족함
- 뜻에 따라 띄어쓰기가 달라짐
- 전문 용어, 제품명, 고유 명칭일 가능성이 있음
- 원문이 방언·캐릭터 말투·문학적 파격일 수 있음
- 원칙형과 허용형이 모두 맞음
- 수정하면 부정·조건·시제·양태·논항이 바뀔 수 있음
- 높임 대상이나 발화 관계가 불명확함
- 인용 범위가 불명확함
## 6. 출처 우선순위
외부 확인이 가능하고 판정이 필요한 경우 다음 순서를 따른다.
1. 국립국어원 한국어 어문 규범·한글 맞춤법
2. 국립국어원 표준어 규정과 표준국어대사전
3. 국립국어원의 표준 문법 연구
4. 국립국어원의 한국어교육 문법·표현 연구
5. 온라인가나다 등 개별 문맥 상담 자료
개별 상담 답변은 규정 본문이나 사전보다 높은 기준으로 사용하지 않는다. 자료가 충돌해 보이면 먼저 품사·뜻·문맥이 같은지 확인하고, 해결되지 않으면 보류한다.
## 7. 수정 비용
같은 규범 적합도를 달성한다면 다음 순서로 선호한다.
1. 공백만 수정
2. 철자 또는 한 어절 수정
3. 짧은 구 수정
4. 문장 재작성
5. 문단 재구성
문장·문단 재작성은 사용자가 명시적으로 윤문이나 표준화를 요청했을 때만 허용한다.
## 8. 최종 자체 검증
출력 전 다음을 비교한다.
- 숫자와 고유 명칭이 동일한가
- 부정·조건·시제·양태가 동일한가
- 보호 구간이 바이트 수준에서 동일한가
- 문체와 높임 등급이 유지됐는가
- 허용형을 오류로 바꾸지 않았는가
- 수정 설명이 실제 수정과 일치하는가
하나라도 확신할 수 없으면 해당 수정만 롤백하고 경고한다.
@@ -0,0 +1,101 @@
# 출력 모드
사용자 요청이 명시적이면 그 형식을 우선한다. 그렇지 않으면 `brief`를 사용한다.
## `silent`
교정문만 반환한다.
```text
<corrected_text>
```
대량 처리나 사용자가 “결과만”을 요청한 경우에 적합하다. 중대한 중의성이 있으면 짧은 경고를 예외적으로 덧붙인다.
## `brief` — 기본값
교정문을 먼저 제시한 뒤, 의미 있는 수정과 경고만 짧게 정리한다.
```markdown
<corrected_text>
수정 사항
- `<original>``<replacement>`: <짧은 근거>
확인이 필요한 부분
- <중의성 또는 보존 이유>
```
수정이 없으면 “교정할 확정 오류를 찾지 못했습니다” 정도로 끝내며, 불필요하게 원문을 반복 설명하지 않는다.
## `teaching`
한국어 학습이나 규칙 설명이 목적일 때 사용한다.
```markdown
## 교정문
<corrected_text>
## 수정 설명
1. 원문 / 수정문
2. 오류 유형
3. 적용 조건
4. 혼동하기 쉬운 반례
```
확정할 수 없는 문법 이론을 하나의 정답처럼 단정하지 않는다.
## `review`
복수 해석이나 전문 용어 가능성이 핵심일 때 사용한다. 원문을 먼저 보존한다.
```markdown
## 제안
- 원문 유지
- 가능한 수정안: ...
## 판단에 필요한 문맥
- ...
```
질문 없이도 안전한 부분은 먼저 교정하고, 막히는 지점만 분리한다.
## `preserve-style`
강제 규범만 교정하고 방언·구어체·말줄임·캐릭터 말투·문장 호흡은 보존한다.
## `standardize`
사용자가 명시적으로 표준어·격식체 통일을 요청했을 때만 사용한다. 변경 범위가 넓어질 수 있으므로 다음을 함께 밝힌다.
- 표준화한 말투와 종결형
- 보존한 고유 명칭과 기술 용어
- 의미 또는 화자 개성이 달라질 수 있어 유지한 부분
## 구조화 출력
도구나 후속 자동화가 요구할 때만 다음 계약을 사용한다.
```json
{
"corrected_text": "...",
"edits": [
{
"span": [0, 0],
"original": "...",
"replacement": "...",
"rule_id": "...",
"severity": "mandatory|suggestion",
"confidence": "A|B|C",
"explanation": "..."
}
],
"warnings": [
{
"type": "ambiguity|missing_context|possible_proper_noun|allowed_variant",
"message": "..."
}
],
"unchanged_protected_spans": ["..."]
}
```
@@ -0,0 +1,116 @@
# 핵심 규칙과 최소 대조 사례
이 문서는 문자열 치환표가 아니다. 각 항목은 **적용 조건과 반례를 함께 확인**할 때만 사용한다.
## 1. 조사와 의존 명사
조사는 앞말에 붙이고 의존 명사는 띄어 쓴다. 같은 표면형이 조사·의존 명사·어미로 갈릴 수 있으므로 앞말의 품사와 뜻을 함께 본다.
| 유지·교정 결과 | 판정 |
|---|---|
| 이것뿐이다 | 체언 뒤 조사 `뿐`: 붙임 |
| 웃을 뿐이다 | 관형사형 뒤 의존 명사 `뿐`: 띄움 |
| 학생만큼 잘한다 | 체언 뒤 조사 `만큼`: 붙임 |
| 노력한 만큼 얻었다 | 관형사형 뒤 의존 명사 `만큼`: 띄움 |
| 약속대로 하세요 | 체언 뒤 조사 `대로`: 붙임 |
| 아는 대로 말하세요 | 관형사형 뒤 의존 명사 `대로`: 띄움 |
| 떠난 지 오래다 | 시간 경과 의존 명사 `지`: 띄움 |
| 갈지 모르겠다 | 불확실성·선택 어미 구성: 붙임 |
| 할 수 있다 | 의존 명사 `수`: 띄움 |
`뿐·만큼·대로·지·만`을 일괄적으로 붙이거나 띄우지 않는다.
## 2. `되/돼`
- `돼``되어`의 준말이다.
- `되어서 → 돼서`, `되었다 → 됐다`
- 자음으로 시작하는 어미 앞에서는 `되`가 유지된다: `되고`, `되면`, `되지`
| 입력 | 처리 |
|---|---|
| 준비가 되서 시작했다 | `준비가 돼서 시작했다` |
| 일이 되면 연락해 | 유지 |
`하/해` 치환법은 설명용 기억법일 뿐 최종 판정 규칙으로 사용하지 않는다.
## 3. `안/않`과 `안되다/안 되다`
- 용언 앞의 짧은 부정은 부사 `안`: `안 간다`
- 긴 부정은 `-지 않다`: `가지 않았다`
- `안되다`가 하나의 단어인 뜻과 `되다`의 부정인 `안 되다`를 구분한다.
| 입력 | 처리 |
|---|---|
| 학교에 않 간다 | `학교에 안 간다` |
| 하지 안았다 | `하지 않았다` |
| 농사가 안돼 걱정이다 | 일이 잘 이루어지지 않는 뜻이면 유지 가능 |
| 여기서 담배를 피우면 안돼요 | 금지·불허 뜻이면 `안 돼요` |
뜻이 불명확하면 자동 수정하지 않는다.
## 4. 종결 어미와 준말
- `-ㄹ게`, `-ㄹ걸`, `-ㄹ수록`은 예사소리로 적는다.
- 의문을 나타내는 `-ㄹ까` 등은 된소리를 유지한다.
| 입력 | 결과 |
|---|---|
| 제가 할께요 | 제가 할게요 |
| 어떻게 할까 | 유지 |
`ㄹ` 뒤 된소리를 일괄 치환하지 않는다.
## 5. 보조 용언과 허용형
보조 용언은 띄어 쓰는 것이 원칙이지만 일부 구성은 붙여 쓰기도 허용된다.
| 입력 | 처리 |
|---|---|
| 비가 올 듯하다 | 원칙형, 유지 |
| 비가 올듯하다 | 허용형, 유지 |
| 비가 올듯 하다 | `비가 올 듯하다` |
| 갈까 보다 | 유지; 앞말에 붙이지 않음 |
생성할 때는 원칙형을 우선하되, 맞는 허용형은 오류로 표시하지 않는다.
## 6. `-든/-던`
- 선택·무관: `-든``가든 말든`
- 과거의 지속·회상·미완: `-던``가던 길`
뜻을 보지 않고 철자만 바꾸지 않는다.
## 7. `로서/로써`
- 자격·지위·신분: `로서`
- 수단·도구: `로써`
사람인지 사물인지가 기준이 아니다.
| 입력 | 결과 |
|---|---|
| 학생으로써 책임을 다했다 | 학생으로서 책임을 다했다 |
| 대화로써 해결했다 | 수단의 뜻이면 유지 |
## 8. 높임과 문체
주체 높임, 객체 높임, 상대 높임을 분리한다. 화자 자신에게 기계적으로 `-시-`를 붙이지 않는다.
- `제가 말씀하시겠습니다`는 발화 관계가 확인되면 `제가 말씀드리겠습니다`를 제안할 수 있다.
- 문맥이 없으면 강제 수정하지 않는다.
- `-습니다`, `-어요`, `-해`, `-한다`의 혼용은 인용·대화 참여자 변경 때문에 정상일 수 있다.
## 9. 의도적 비표준·구어체
방언, 신조어, 업계 표현, 캐릭터 말투, 반복, 말줄임표, 이모티콘은 사용자의 의도를 담을 수 있다. 표준화 요청이 없으면 경고 또는 제안만 하고 원문을 보존한다.
## 10. 자연스러움과 간결성
불필요한 피동, 중복 표현, 과도한 명사화는 기본적으로 오류가 아니라 스타일 후보다. 다음 조건을 모두 만족할 때만 수정한다.
- 사용자가 윤문·간결화를 요청함
- 기술적 의미와 단정 강도가 유지됨
- 주체와 정보 초점이 바뀌지 않음
- 더 짧은 수정으로 같은 효과를 얻을 수 없음
근거가 없으면 “더 자연스럽다”라는 설명을 만들지 않는다.
@@ -0,0 +1,32 @@
# 조사 자료 기반과 범위
이 스킬은 제공된 「한국어 문법·표현 교정 에이전트 스킬 설계 보고서」에서 다음 내용을 추출해 구성했다.
- 보수적 교정과 정밀도 우선 원칙
- 의미·사실·문체·보호 구간 불변식
- 공식 규범과 사전의 출처 우선순위
- 조사·의존 명사·활용·보조 용언·높임의 대표 규칙
- 허용형 보존과 중의성 보류 정책
- 피드백 모드
- 일반·어려운·회귀 테스트 27건
- 출시 지표와 회귀 방지 기준
## 지원 범위
- 표준어 기반의 일반 한국어
- 맞춤법, 띄어쓰기, 활용, 조사, 어미, 높임, 기본 표현 교정
- 원문의 의미와 의도적 문체를 보존하는 제한적 윤문
- 마크다운, 코드, URL, 명령어가 섞인 기술 문서
## 비지원 또는 제한 범위
조사 보고서만으로 다음 영역의 깊은 품질 기준은 충분히 정의되지 않았다.
- 문학·광고·브랜드 카피의 창작 문체
- 특정 작가나 매체의 문체 모사
- 기술 블로그 특유의 서사 구조와 독자 설계
- AI 문체 탐지 자체
- 최신 신조어·업계 용어의 포괄적 사전
- 법률·의학 등 고위험 분야의 전문 용어 판정
이 영역은 별도 장르 스킬이나 도메인 자료를 추가해 확장한다. 현재 스킬은 확인되지 않은 규칙을 일반 지식으로 보충하지 않고 보류한다.
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
from __future__ import annotations
import json
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIRED = [
ROOT / "SKILL.md",
ROOT / "references" / "decision-policy.md",
ROOT / "references" / "rule-catalog.md",
ROOT / "references" / "output-modes.md",
ROOT / "tests" / "cases.json",
ROOT / "tests" / "evaluation-rubric.md",
]
def fail(message: str) -> None:
print(f"FAIL: {message}")
raise SystemExit(1)
def parse_frontmatter(text: str) -> dict[str, str]:
match = re.match(r"^---\n(.*?)\n---\n", text, re.S)
if not match:
fail("SKILL.md must begin with YAML frontmatter")
data: dict[str, str] = {}
for line in match.group(1).splitlines():
if not line.strip() or line.lstrip().startswith("#"):
continue
if ":" not in line:
fail(f"invalid frontmatter line: {line!r}")
key, value = line.split(":", 1)
data[key.strip()] = value.strip().strip('"').strip("'")
return data
def main() -> None:
missing = [str(path.relative_to(ROOT)) for path in REQUIRED if not path.exists()]
if missing:
fail("missing required files: " + ", ".join(missing))
skill_text = (ROOT / "SKILL.md").read_text(encoding="utf-8")
frontmatter = parse_frontmatter(skill_text)
name = frontmatter.get("name", "")
description = frontmatter.get("description", "")
if name != ROOT.name:
fail(f"frontmatter name {name!r} must match directory {ROOT.name!r}")
if not re.fullmatch(r"[A-Za-z0-9-]+", name):
fail("name must contain only letters, numbers, and hyphens")
if not description.startswith("Use when "):
fail("description must start with 'Use when '")
if len((name + description).encode("utf-8")) > 1024:
fail("name + description frontmatter exceeds 1024 bytes")
if "cite" in skill_text or "turn" in frontmatter.get("description", ""):
fail("runtime-specific citation markers must not appear in SKILL.md")
cases = json.loads((ROOT / "tests" / "cases.json").read_text(encoding="utf-8"))
if not isinstance(cases, list) or not cases:
fail("tests/cases.json must be a non-empty array")
ids: set[str] = set()
allowed_actions = {"correct", "keep", "suggest", "review"}
required_keys = {"id", "category", "input", "expected_text", "expected_action", "rule_id", "explanation"}
for index, case in enumerate(cases):
missing_keys = required_keys - set(case)
if missing_keys:
fail(f"case #{index} missing keys: {sorted(missing_keys)}")
if case["id"] in ids:
fail(f"duplicate case id: {case['id']}")
ids.add(case["id"])
if case["expected_action"] not in allowed_actions:
fail(f"invalid expected_action in {case['id']}: {case['expected_action']}")
print(f"PASS: package structure valid; {len(cases)} test cases loaded")
if __name__ == "__main__":
main()
@@ -0,0 +1,245 @@
[
{
"id": "G-001",
"category": "general",
"input": "꽃 에서부터입니다.",
"expected_text": "꽃에서부터입니다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-PARTICLE-001",
"explanation": "조사는 앞말에 붙이고 조사 연속체도 띄지 않는다."
},
{
"id": "G-002",
"category": "general",
"input": "이 일은 할수있다.",
"expected_text": "이 일은 할 수 있다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-NNB-SU-001",
"explanation": "의존 명사 '수'와 뒤의 '있다'를 각각 띄어 쓴다."
},
{
"id": "G-003",
"category": "general",
"input": "그는 웃을뿐이다.",
"expected_text": "그는 웃을 뿐이다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-NNB-PPUN-001",
"explanation": "관형사형 뒤의 '뿐'은 의존 명사이다."
},
{
"id": "G-004",
"category": "general",
"input": "이것 뿐이다.",
"expected_text": "이것뿐이다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-JX-PPUN-001",
"explanation": "체언 뒤의 '뿐'은 조사이다."
},
{
"id": "G-005",
"category": "general",
"input": "노력한만큼 성과가 났다.",
"expected_text": "노력한 만큼 성과가 났다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-NNB-MANKUM-001",
"explanation": "관형사형 뒤의 '만큼'은 의존 명사이다."
},
{
"id": "G-006",
"category": "general",
"input": "학생 만큼 잘한다.",
"expected_text": "학생만큼 잘한다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-JX-MANKUM-001",
"explanation": "체언 뒤에서 비교 정도를 나타내는 '만큼'은 조사이다."
},
{
"id": "G-007",
"category": "general",
"input": "제가 할께요.",
"expected_text": "제가 할게요.",
"expected_action": "correct",
"rule_id": "KO-ENDING-LGE-001",
"explanation": "종결 어미 '-ㄹ게'는 예사소리로 적는다."
},
{
"id": "G-008",
"category": "general",
"input": "준비가 되서 시작했다.",
"expected_text": "준비가 돼서 시작했다.",
"expected_action": "correct",
"rule_id": "KO-CONTRACTION-DOE-001",
"explanation": "'돼서'는 '되어서'의 준말이다."
},
{
"id": "G-009",
"category": "general",
"input": "오늘은 학교에 않 간다.",
"expected_text": "오늘은 학교에 안 간다.",
"expected_action": "correct",
"rule_id": "KO-NEGATION-AN-001",
"explanation": "용언 앞의 짧은 부정은 부사 '안'을 쓴다."
},
{
"id": "G-010",
"category": "general",
"input": "숙제를 하지 안았다.",
"expected_text": "숙제를 하지 않았다.",
"expected_action": "correct",
"rule_id": "KO-NEGATION-ANH-001",
"explanation": "긴 부정은 '-지 않다'로 구성한다."
},
{
"id": "H-001",
"category": "hard",
"input": "이것뿐이고, 내가 한 일은 기다렸을 뿐이다.",
"expected_text": "이것뿐이고, 내가 한 일은 기다렸을 뿐이다.",
"expected_action": "keep",
"rule_id": "KO-PPUN-DISAMBIGUATION-001",
"explanation": "첫 '뿐'은 조사이고 둘째 '뿐'은 의존 명사이다."
},
{
"id": "H-002",
"category": "hard",
"input": "학생만큼 노력한 만큼 결과가 나왔다.",
"expected_text": "학생만큼 노력한 만큼 결과가 나왔다.",
"expected_action": "keep",
"rule_id": "KO-MANKUM-DISAMBIGUATION-001",
"explanation": "첫 '만큼'은 조사, 둘째는 의존 명사이다."
},
{
"id": "H-003",
"category": "hard",
"input": "그가 떠난지 알 수 없다.",
"expected_text": "그가 떠난 지 알 수 없다.",
"expected_action": "correct",
"rule_id": "KO-SPACING-NNB-JI-001",
"explanation": "이 문맥에서는 떠난 뒤 경과한 시간을 뜻하는 의존 명사로 해석한다."
},
{
"id": "H-004",
"category": "hard",
"input": "그가 떠날 지 알 수 없다.",
"expected_text": "그가 떠날지 알 수 없다.",
"expected_action": "correct",
"rule_id": "KO-ENDING-JI-001",
"explanation": "떠날 것인지의 불확실성을 나타내는 어미 구성이다."
},
{
"id": "H-005",
"category": "hard",
"input": "비가 올듯하다.",
"expected_text": "비가 올듯하다.",
"expected_action": "keep",
"rule_id": "KO-AUX-DDEUT-ALLOW-001",
"explanation": "붙여 쓰기가 허용되는 형태이므로 오교정하지 않는다."
},
{
"id": "H-006",
"category": "hard",
"input": "비가 올듯 하다.",
"expected_text": "비가 올 듯하다.",
"expected_action": "correct",
"rule_id": "KO-AUX-DDEUT-001",
"explanation": "원칙형은 '올 듯하다'이고 허용형은 '올듯하다'이다."
},
{
"id": "H-007",
"category": "hard",
"input": "학생으로써 책임을 다했다.",
"expected_text": "학생으로서 책임을 다했다.",
"expected_action": "correct",
"rule_id": "KO-PARTICLE-ROSEO-001",
"explanation": "학생이라는 자격을 나타내므로 '로서'를 쓴다."
},
{
"id": "H-008",
"category": "hard",
"input": "올해 농사가 안돼 걱정이다.",
"expected_text": "올해 농사가 안돼 걱정이다.",
"expected_action": "keep",
"rule_id": "KO-LEXEME-ANDWEDA-001",
"explanation": "농사가 잘 이루어지지 않는다는 뜻의 한 단어 '안되다' 활용으로 볼 수 있다."
},
{
"id": "H-009",
"category": "hard",
"input": "여기에서는 담배를 피우면 안돼요.",
"expected_text": "여기에서는 담배를 피우면 안 돼요.",
"expected_action": "correct",
"rule_id": "KO-NEGATION-AN-DOEDA-001",
"explanation": "허용되지 않는다는 의미의 '되다' 부정문이므로 '안 돼요'로 띄어 쓴다."
},
{
"id": "H-010",
"category": "hard",
"input": "제가 말씀하시겠습니다.",
"expected_text": "제가 말씀드리겠습니다.",
"expected_action": "suggest",
"rule_id": "KO-HONORIFIC-HUMBLE-001",
"explanation": "일인칭 화자 자신에게 주체 높임 '-시-'를 쓰기보다 겸양 동사를 쓰는 것이 적절하다. 발화 상황이 없으므로 강제 수정이 아니라 제안으로 처리한다."
},
{
"id": "R-001",
"category": "regression",
"input": "갈까 보다.",
"expected_text": "갈까 보다.",
"expected_action": "keep",
"rule_id": "KO-AUX-ENDING-BOUNDARY-001",
"explanation": "종결 어미 '-ㄹ까' 뒤의 '보다'를 앞말에 붙이지 않는다."
},
{
"id": "R-002",
"category": "regression",
"input": "가든 말든 네가 정해.",
"expected_text": "가든 말든 네가 정해.",
"expected_action": "keep",
"rule_id": "KO-ENDING-DEUN-001",
"explanation": "선택·무관의 뜻이므로 '-든'이 맞다."
},
{
"id": "R-003",
"category": "regression",
"input": "그가 가던 길을 바라봤다.",
"expected_text": "그가 가던 길을 바라봤다.",
"expected_action": "keep",
"rule_id": "KO-ENDING-DEON-001",
"explanation": "과거의 지속·회상을 나타내므로 '-던'을 보존한다."
},
{
"id": "R-004",
"category": "regression",
"input": "문서의 `할수있다` 필드는 변경하지 마세요.",
"expected_text": "문서의 `할수있다` 필드는 변경하지 마세요.",
"expected_action": "keep",
"rule_id": "KO-PROTECT-INLINE-CODE-001",
"explanation": "인라인 코드 내부 문자열은 교정하지 않는다."
},
{
"id": "R-005",
"category": "regression",
"input": "https://example.com/할수있다 를 확인하세요.",
"expected_text": "https://example.com/할수있다 를 확인하세요.",
"expected_action": "keep",
"rule_id": "KO-PROTECT-URL-001",
"explanation": "URL 내부 문자열은 변경하지 않는다."
},
{
"id": "R-006",
"category": "regression",
"input": "비가 올 듯하다.",
"expected_text": "비가 올 듯하다.",
"expected_action": "keep",
"rule_id": "KO-AUX-DDEUT-001",
"explanation": "원칙형인 올바른 입력을 다시 붙이거나 분리하지 않는다."
},
{
"id": "R-007",
"category": "regression",
"input": "이것뿐이다.",
"expected_text": "이것뿐이다.",
"expected_action": "keep",
"rule_id": "KO-SPACING-JX-PPUN-001",
"explanation": "조사 '뿐'을 의존 명사로 오인하여 띄지 않는다."
}
]
@@ -0,0 +1,68 @@
# 평가 기준
## 평가 원칙
교정 결과는 문자열 완전 일치만으로 평가하지 않는다. **탐지, 수정, 설명, 보존, 보류**를 분리해 평가한다. 정밀도를 재현율보다 우선하며, 중대한 의미 변형과 보호 구간 손상은 한 건도 허용하지 않는다.
## 출시 기준
| 평가 축 | 기준 | 측정 방식 |
|---|---:|---|
| 확정 오류 정밀도 | 99% 이상 | 확정 필수 교정에서 정확한 수정 수 / 전체 자동 수정 수 |
| 전체 교정 정밀도 | 97% 이상 | 일반·어려운 사례 혼합 |
| 확정 오류 재현율 | 95% 이상 | 필요한 필수 교정 중 성공 비율 |
| F0.5 | 97% 이상 | 정밀도에 더 큰 가중치 |
| 중대 의미 변형 | 0건 | 부정·조건·시제·양태·주체·수치 비교 |
| 보호 구간 보존 | 100% | 코드·URL·인용·숫자 스냅샷 비교 |
| 문체·높임 보존 | 99% 이상 | 종결형과 높임 표현 비교 |
| 허용형 오교정 | 0.5% 이하 | 원칙·허용 공존 사례 |
| 애매 사례 보류 정확도 | 95% 이상 | 문맥 의존 사례에서 `review` 또는 `suggest` 판정 |
| 회귀 통과율 | 100% | `tests/cases.json` 전체 |
| 설명 일치율 | 98% 이상 | `rule_id`와 실제 편집 일치 |
## 테스트 실행 방법
각 테스트를 스킬 없이 실행한 결과와 스킬을 로드한 결과로 나눈다.
1. 새 대화 또는 격리된 에이전트에서 스킬 없이 입력한다.
2. `expected_text`, `expected_action`, `rule_id`와 비교한다.
3. 같은 입력을 스킬과 함께 실행한다.
4. 새 오교정이 생기면 해당 사례를 회귀 세트에 추가한다.
5. 올바른 입력을 유지하는 음성 테스트를 양성 테스트와 같은 비중으로 관리한다.
## 판정 항목
테스트마다 다음을 기록한다.
```yaml
case_id: G-001
actual_text: "..."
actual_action: correct|keep|suggest|review
actual_rule_id: "..."
semantic_preservation: pass|fail
protected_span_preservation: pass|fail
style_preservation: pass|fail
notes: "..."
```
## 중대 실패
다음 중 하나라도 발생하면 전체 결과를 실패로 처리한다.
- 긍정과 부정이 바뀜
- 조건·예외·시제·가능성의 강도가 바뀜
- 숫자·날짜·단위·버전이 바뀜
- 코드·URL·전자 우편·경로·식별자가 바뀜
- 인명·제품명·전문 용어를 일반어로 강제 치환함
- 맞는 허용형을 오류로 단정함
- 문맥이 필요한 사례를 확정적으로 자동 수정함
## 회귀 세트 확장 규칙
실제 사용 중 문제가 발견되면 다음 순서로 반영한다.
1. 문제 입력과 잘못된 출력을 고정한다.
2. 기대 행동을 `correct`, `keep`, `suggest`, `review` 중 하나로 명시한다.
3. 스킬 수정 전 실패를 확인한다.
4. 최소한의 규칙만 보강한다.
5. 전체 테스트를 다시 실행한다.
@@ -0,0 +1,63 @@
# 에이전트 적용 시나리오
이 파일은 별도 에이전트나 새 대화에서 스킬의 실제 준수 여부를 확인하기 위한 시나리오다. 같은 시나리오를 **스킬 없음 / 스킬 있음** 조건으로 각각 5회 이상 실행한다.
## 시나리오 1: 빠른 일괄 교정 압박
```text
마감이 급합니다. 다음 글의 띄어쓰기를 전부 자동으로 통일하세요. 설명은 필요 없습니다.
이것뿐이고, 내가 한 일은 기다렸을 뿐이다. 학생만큼 노력한 만큼 결과가 나왔다.
```
기대: `뿐`, `만큼`을 일괄 처리하지 않고 원문을 유지한다.
## 시나리오 2: 보호 구간 무시 압박
```text
오타가 하나라도 남으면 안 됩니다. 코드와 링크까지 포함해서 전부 고쳐 주세요.
문서의 `할수있다` 필드와 https://example.com/할수있다 를 확인하고, 이 일은 할수있다.
```
기대: 코드와 URL은 보존하고 마지막 `할수있다``할 수 있다`로 교정한다.
## 시나리오 3: 자연스러움 명목의 의미 강화
```text
아래 문장을 자신감 있고 매끄럽게 윤문하세요.
이 구조는 토큰 노출 위험을 줄일 수 있습니다.
```
기대: `방지합니다`, `완전히 제거합니다`처럼 단정 강도를 높이지 않는다.
## 시나리오 4: 허용형 강제 통일
```text
맞춤법을 엄격히 적용해 틀린 부분은 전부 바로잡으세요.
비가 올듯하다. 비가 올 듯하다.
```
기대: 두 표현 모두 허용되는 입력으로 유지한다.
## 시나리오 5: 문맥 없는 높임 수정
```text
다음 문장을 무조건 올바른 존댓말로 고쳐 주세요.
제가 말씀하시겠습니다.
```
기대: 강제 교정보다 `제가 말씀드리겠습니다`를 제안하고 발화 맥락의 영향을 밝힌다.
## 관찰할 실패 패턴
- 문자열 일괄 치환
- 허용형 오교정
- 보호 구간 손상
- 의미·양태 강화
- 방언·말투 삭제
- 문맥 없는 확정 판정
- 실제 수정과 맞지 않는 문법 설명