chore: snapshot working tree before harness removal
미추적 파일과 미커밋 수정을 전부 담아 pre-harness-removal 태그의 복구 범위를 확보한다. .agents/skills/writing-natural-korean 9개와 korean-technical-blog-skills-bundle-v1 61개가 여기 포함된다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b101b6e717
commit
1099834617
@@ -0,0 +1,58 @@
|
||||
7630620a1b7231f5e1163c41f643e1b95ad1b081371db7c22835d6fca4acf483 README.md
|
||||
88bb893acdced5d03be8ee657aacf51436d57f29c35241ad559f9da560dc3ad8 editing-korean-grammar-and-expression/README.md
|
||||
7b30f057335ef5343762c9b95f6f7c6e4c8ced83b490d1a248394e617ea6315c editing-korean-grammar-and-expression/SKILL.md
|
||||
3dbee5f3dfd935698ea8b37b65c9c91d2a12ce31200dfeb57c7afedcdadf9cf3 editing-korean-grammar-and-expression/references/decision-policy.md
|
||||
53258e2a1ec7091c5aac15a837776d27659c8912360d07138e4d227ca8252228 editing-korean-grammar-and-expression/references/output-modes.md
|
||||
0d0ad5d87b5f0c94fd1d95c65003591eed40450a89e2bed1ea0e7687ce3b14e9 editing-korean-grammar-and-expression/references/rule-catalog.md
|
||||
5bbe200ede5c7ca85ffb094c9dd01fdcaef3b6371f88a5f518f45fe4f414ed46 editing-korean-grammar-and-expression/references/source-basis.md
|
||||
5f87b3f8a8f50c08db829e5dd14905970d40c5f79cf005fa81ef478849e1fd6c editing-korean-grammar-and-expression/scripts/validate_skill.py
|
||||
f096d85c1256cb2dddea86107e12beee36949619fd04ec8cb9d38316ded70f7e editing-korean-grammar-and-expression/tests/cases.json
|
||||
ded7fcfb1a7f6fed9e5396f4a1dd6d35947de626a2c644e395a571906a1f5324 editing-korean-grammar-and-expression/tests/evaluation-rubric.md
|
||||
95e0b66aa3ed103548245e781f47541781b9cede7a9a30892ad75000e38d948b editing-korean-grammar-and-expression/tests/pressure-scenarios.md
|
||||
cf2f5554341c83c87dc3778949fc74b5ef7f067236b42435a9797834d2d2d10a reducing-ai-like-korean-writing/README.md
|
||||
ecbe2056f40780a0f37d292b6725e73fc5842bc9b129f3061dad8f568d187865 reducing-ai-like-korean-writing/SKILL.md
|
||||
8e2497974b6c0449a42bebddd83e3e797510633cac8a38c15e6237209b2d4531 reducing-ai-like-korean-writing/references/decision-policy.md
|
||||
bcca95cbee25c11fb2267245d2a58c9960b9a68a08048eaa52ada7775a807126 reducing-ai-like-korean-writing/references/genre-profiles.md
|
||||
20405fd7fdc6c62cefcc48a377708162f6f5f5202b92179baa54b03ea6f561f4 reducing-ai-like-korean-writing/references/output-modes.md
|
||||
6807778f2058346438d4903929b23dbbff83a9f253810368e4e1dda09a6897c8 reducing-ai-like-korean-writing/references/pattern-catalog.md
|
||||
2f9a87913c259e41eae59ee62380849751382e5418c4e67279aad23d6bfdb769 reducing-ai-like-korean-writing/references/source-basis.md
|
||||
444ee79893e6c528988557031095f15ccb399c6b1a46ce4ee804739db8a8bbba reducing-ai-like-korean-writing/scripts/validate_skill.py
|
||||
7d42fd42febfeb08bef466f83409b4d7a1ff94957fba86bad26d2f44ab5acf37 reducing-ai-like-korean-writing/tests/baseline-observations.md
|
||||
28f62b648ba5185cc45b66916277f1eee8aaa591c676ca9d74881b6e16e53beb reducing-ai-like-korean-writing/tests/cases.json
|
||||
2ad2fd862c06e549f5601d4ceacaaab9a468c56ff5b9788875427f168822eb32 reducing-ai-like-korean-writing/tests/evaluation-rubric.md
|
||||
d06418dcfc991ce6afec168d6bb5f0be129d05f8048bb686acd3ba7937855e9f reducing-ai-like-korean-writing/tests/pressure-scenarios.md
|
||||
9a1a4da5650006da39a0f0300aefb7ee1acc341fe99acfc6ae775f513a0c2b3a writing-korean-technical-blogs/README.md
|
||||
89fef42eb8f2bb7ce5626c3303b49ec366413c7e8f3aa2d4552c1470559aed56 writing-korean-technical-blogs/SKILL.md
|
||||
5a036ef405358370c3162d659f0900c33c588fb14fd1be71513e3cc13e5db377 writing-korean-technical-blogs/examples/end-to-end-performance-case.md
|
||||
a800700eacc32f834736f082380687f65a962de72c7aff1b29ea132bb03ba5c1 writing-korean-technical-blogs/examples/revision-pairs.jsonl
|
||||
26473dddaa0695d5a0dbd7c6d9a3da77dfd99e686650a27d789f51d4929a12bc writing-korean-technical-blogs/lexicons/formulaic-openings-and-closings.yaml
|
||||
741bf512903ed0bcdb3c43dc4575c65e00bd6fd413fe238b9ce331eb8e751c29 writing-korean-technical-blogs/lexicons/product-names.example.yaml
|
||||
db4c48c7d0a6c20c46f7ea82fb9ba28a645462a5e2f045498703f4ada746437e writing-korean-technical-blogs/lexicons/protected-identifiers.example.yaml
|
||||
0eee62d3891f6499b2682e36a9418297d6aec66c9217440504e1dc9a2b52d18b writing-korean-technical-blogs/lexicons/vague-expressions.yaml
|
||||
910c52906d19bd29c068f9696f2edcc81c2149d4c06b6bb3ee052eb048921667 writing-korean-technical-blogs/profiles/architecture-decision.yaml
|
||||
2b8a37f5dc61af83fd224ce25be614f5d6f30b7a9ca9af768b64d0c3d56b77ac writing-korean-technical-blogs/profiles/conversational-tech.yaml
|
||||
557ea745b8c517d8535b9787399245317a98c328b9a2da3b00f2e393d6a19113 writing-korean-technical-blogs/profiles/default-formal.yaml
|
||||
86528843f3efc5288121dfa2b1b13db1c1ed90c27334d0e3fe65b53802435b34 writing-korean-technical-blogs/profiles/incident-postmortem.yaml
|
||||
3f59159555be2e300c0944f36b5753228232064ce89daf11acc4212c1a2a5cd5 writing-korean-technical-blogs/profiles/migration-case-study.yaml
|
||||
1635d41c396bbb5f133c9c6a3535f76f7d5bd61f5a67f029d53cf0829d4f5c62 writing-korean-technical-blogs/profiles/performance-case-study.yaml
|
||||
d4be41789818f1cdafed59f24a1d18a719153f48bfb1d9024888d356f9261f4e writing-korean-technical-blogs/profiles/recruitment-tech-content.yaml
|
||||
52412ea45369baad5d0f715bc45e0abcf3de0d87184d3e6e1b491cf98f384c25 writing-korean-technical-blogs/profiles/tooling-adoption.yaml
|
||||
77f56eefa54db15f00adede694a0f7f61a1c2d87464ca12cfc0365bc8c817b58 writing-korean-technical-blogs/profiles/tutorial-lab.yaml
|
||||
407136db136e7a27afc4a5c6ed635a0d479b5b4372370fd8af3a44ab94c4bdfd writing-korean-technical-blogs/references/decision-policy.md
|
||||
58013844347c1e02a7183a4320e000cfef089d29e704f054f4a5bc7f40919ff0 writing-korean-technical-blogs/references/enterprise-blog-patterns.md
|
||||
0846e1b5293de602e15f52dec4f9776f5e302d101df4abd8356b69b6186492b5 writing-korean-technical-blogs/references/evidence-and-source-policy.md
|
||||
ba935624b8d143d573c85a05f4d931ec6bda9959ce3ef48eb69ff6b55b44a6ea writing-korean-technical-blogs/references/exceptions.md
|
||||
97f93c70523bf0cc1fcf0cad351a69b48d702420bd45bbc2841c6236df1a794e writing-korean-technical-blogs/references/output-modes.md
|
||||
849fba1475eac2ff5258e80be8a3f1cc9cd49c013ca9ed703b5a8ac112bf4b60 writing-korean-technical-blogs/references/rule-catalog.md
|
||||
3b933fa88f52f5e596f8231b0b128d5ca86b28cc452db91864a66e3d3d3b79a4 writing-korean-technical-blogs/references/source-basis.md
|
||||
88047b6409edb2b1e8705b1a5431bbb7f594ef8cb32fd43765a6c5d03da39803 writing-korean-technical-blogs/references/structure-patterns.md
|
||||
db85244892b698fc3dc424972920074f43f970d4ebccc09354eb1f3a891ce0d8 writing-korean-technical-blogs/references/titles-introductions-conclusions.md
|
||||
c110176b07a4a4edf75c9aa6edc374e08250be9a27bef0823b2f41ed085d6b8d writing-korean-technical-blogs/schemas/article-brief.schema.json
|
||||
417548ed4936633bdff7fb4aa87683130636932dfebe44c541c4b0fd426deb70 writing-korean-technical-blogs/schemas/article-result.schema.json
|
||||
9537896cb1914a8b6537aaa6b27d51b0e06e94bc60280a8ff1990f5904e4532c writing-korean-technical-blogs/schemas/rubric.schema.json
|
||||
ccd2fbe9b8c87af814eae9790df863b50b93f518cc1ba871ef2930ddac54c3e3 writing-korean-technical-blogs/scripts/validate_skill.py
|
||||
343d04ca2c1f5139a94176420417d5481aeaccfefdf6f4f09cd31a1654ed1201 writing-korean-technical-blogs/tests/baseline-observations.md
|
||||
50772b7b691fc86631b5e4ae35997d9c9ef056662eb43a76500c9ff27c239a09 writing-korean-technical-blogs/tests/cases.json
|
||||
03e73c9a515449f2a8a0162d1b90176f23d75efbf5d2ef255592dd8cf39a9d21 writing-korean-technical-blogs/tests/evaluation-rubric.md
|
||||
cfb996bb669ac09e3ffded859f421c8f30162c34eedf69446a6c85f9876bd961 writing-korean-technical-blogs/tests/pressure-scenarios.md
|
||||
6605eef379ba9e91d2ee4a60a9b28b36aa50a87037c89264afc601cf59515949 writing-korean-technical-blogs/tests/workflow.jsonl
|
||||
@@ -0,0 +1,34 @@
|
||||
# 한국어 기술 블로그 Agent Skills 번들
|
||||
|
||||
다음 세 스킬을 함께 설치하는 번들이다.
|
||||
|
||||
1. `writing-korean-technical-blogs`
|
||||
- 자료를 기술 블로그의 문제·제약·선택·구현·결과·한계 구조로 작성·재구성한다.
|
||||
2. `reducing-ai-like-korean-writing`
|
||||
- 상투성, 추상화, 반복, 과잉 구조화를 줄이되 사실과 기술 의미를 보존한다.
|
||||
3. `editing-korean-grammar-and-expression`
|
||||
- 최종 맞춤법, 띄어쓰기, 문법, 호응을 보수적으로 검수한다.
|
||||
|
||||
## 권장 실행 순서
|
||||
|
||||
```text
|
||||
원자료와 초안
|
||||
→ writing-korean-technical-blogs
|
||||
→ reducing-ai-like-korean-writing
|
||||
→ editing-korean-grammar-and-expression
|
||||
→ 사실·수치·코드·인용 최종 대조
|
||||
```
|
||||
|
||||
## 하네스와의 경계
|
||||
|
||||
이 번들은 한 편의 글을 작성하는 전문 능력을 제공한다. 다음까지 필요하면 세 스킬 위에 별도 `technical-blog-production` 하네스를 둔다.
|
||||
|
||||
- 다중 출처 조사와 출처 수집
|
||||
- 코드·명령어 실제 실행 검증
|
||||
- 이미지와 다이어그램 제작
|
||||
- 중간 산출물과 재시작 상태 관리
|
||||
- CMS 게시와 배포 확인
|
||||
|
||||
## 설치
|
||||
|
||||
번들 안의 세 폴더를 Agent Skills 디렉터리 아래에 각각 복사한다. 번들 루트 자체를 하나의 스킬로 설치하지 않는다.
|
||||
+44
@@ -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`로 회귀 검증한다.
|
||||
+111
@@ -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. 최종 자체 검증
|
||||
|
||||
출력 전 다음을 비교한다.
|
||||
|
||||
- 숫자와 고유 명칭이 동일한가
|
||||
- 부정·조건·시제·양태가 동일한가
|
||||
- 보호 구간이 바이트 수준에서 동일한가
|
||||
- 문체와 높임 등급이 유지됐는가
|
||||
- 허용형을 오류로 바꾸지 않았는가
|
||||
- 수정 설명이 실제 수정과 일치하는가
|
||||
|
||||
하나라도 확신할 수 없으면 해당 수정만 롤백하고 경고한다.
|
||||
+101
@@ -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": ["..."]
|
||||
}
|
||||
```
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
# 핵심 규칙과 최소 대조 사례
|
||||
|
||||
이 문서는 문자열 치환표가 아니다. 각 항목은 **적용 조건과 반례를 함께 확인**할 때만 사용한다.
|
||||
|
||||
## 1. 조사와 의존 명사
|
||||
|
||||
조사는 앞말에 붙이고 의존 명사는 띄어 쓴다. 같은 표면형이 조사·의존 명사·어미로 갈릴 수 있으므로 앞말의 품사와 뜻을 함께 본다.
|
||||
|
||||
| 유지·교정 결과 | 판정 |
|
||||
|---|---|
|
||||
| 이것뿐이다 | 체언 뒤 조사 `뿐`: 붙임 |
|
||||
| 웃을 뿐이다 | 관형사형 뒤 의존 명사 `뿐`: 띄움 |
|
||||
| 학생만큼 잘한다 | 체언 뒤 조사 `만큼`: 붙임 |
|
||||
| 노력한 만큼 얻었다 | 관형사형 뒤 의존 명사 `만큼`: 띄움 |
|
||||
| 약속대로 하세요 | 체언 뒤 조사 `대로`: 붙임 |
|
||||
| 아는 대로 말하세요 | 관형사형 뒤 의존 명사 `대로`: 띄움 |
|
||||
| 떠난 지 오래다 | 시간 경과 의존 명사 `지`: 띄움 |
|
||||
| 갈지 모르겠다 | 불확실성·선택 어미 구성: 붙임 |
|
||||
| 할 수 있다 | 의존 명사 `수`: 띄움 |
|
||||
|
||||
`뿐·만큼·대로·지·만`을 일괄적으로 붙이거나 띄우지 않는다.
|
||||
|
||||
## 2. `되/돼`
|
||||
|
||||
- `돼`는 `되어`의 준말이다.
|
||||
- `되어서 → 돼서`, `되었다 → 됐다`
|
||||
- 자음으로 시작하는 어미 앞에서는 `되`가 유지된다: `되고`, `되면`, `되지`
|
||||
|
||||
| 입력 | 처리 |
|
||||
|---|---|
|
||||
| 준비가 되서 시작했다 | `준비가 돼서 시작했다` |
|
||||
| 일이 되면 연락해 | 유지 |
|
||||
|
||||
`하/해` 치환법은 설명용 기억법일 뿐 최종 판정 규칙으로 사용하지 않는다.
|
||||
|
||||
## 3. `안/않`과 `안되다/안 되다`
|
||||
|
||||
- 용언 앞의 짧은 부정은 부사 `안`: `안 간다`
|
||||
- 긴 부정은 `-지 않다`: `가지 않았다`
|
||||
- `안되다`가 하나의 단어인 뜻과 `되다`의 부정인 `안 되다`를 구분한다.
|
||||
|
||||
| 입력 | 처리 |
|
||||
|---|---|
|
||||
| 학교에 않 간다 | `학교에 안 간다` |
|
||||
| 하지 안았다 | `하지 않았다` |
|
||||
| 농사가 안돼 걱정이다 | 일이 잘 이루어지지 않는 뜻이면 유지 가능 |
|
||||
| 여기서 담배를 피우면 안돼요 | 금지·불허 뜻이면 `안 돼요` |
|
||||
|
||||
뜻이 불명확하면 자동 수정하지 않는다.
|
||||
|
||||
## 4. 종결 어미와 준말
|
||||
|
||||
- `-ㄹ게`, `-ㄹ걸`, `-ㄹ수록`은 예사소리로 적는다.
|
||||
- 의문을 나타내는 `-ㄹ까` 등은 된소리를 유지한다.
|
||||
|
||||
| 입력 | 결과 |
|
||||
|---|---|
|
||||
| 제가 할께요 | 제가 할게요 |
|
||||
| 어떻게 할까 | 유지 |
|
||||
|
||||
`ㄹ` 뒤 된소리를 일괄 치환하지 않는다.
|
||||
|
||||
## 5. 보조 용언과 허용형
|
||||
|
||||
보조 용언은 띄어 쓰는 것이 원칙이지만 일부 구성은 붙여 쓰기도 허용된다.
|
||||
|
||||
| 입력 | 처리 |
|
||||
|---|---|
|
||||
| 비가 올 듯하다 | 원칙형, 유지 |
|
||||
| 비가 올듯하다 | 허용형, 유지 |
|
||||
| 비가 올듯 하다 | `비가 올 듯하다` |
|
||||
| 갈까 보다 | 유지; 앞말에 붙이지 않음 |
|
||||
|
||||
생성할 때는 원칙형을 우선하되, 맞는 허용형은 오류로 표시하지 않는다.
|
||||
|
||||
## 6. `-든/-던`
|
||||
|
||||
- 선택·무관: `-든` — `가든 말든`
|
||||
- 과거의 지속·회상·미완: `-던` — `가던 길`
|
||||
|
||||
뜻을 보지 않고 철자만 바꾸지 않는다.
|
||||
|
||||
## 7. `로서/로써`
|
||||
|
||||
- 자격·지위·신분: `로서`
|
||||
- 수단·도구: `로써`
|
||||
|
||||
사람인지 사물인지가 기준이 아니다.
|
||||
|
||||
| 입력 | 결과 |
|
||||
|---|---|
|
||||
| 학생으로써 책임을 다했다 | 학생으로서 책임을 다했다 |
|
||||
| 대화로써 해결했다 | 수단의 뜻이면 유지 |
|
||||
|
||||
## 8. 높임과 문체
|
||||
|
||||
주체 높임, 객체 높임, 상대 높임을 분리한다. 화자 자신에게 기계적으로 `-시-`를 붙이지 않는다.
|
||||
|
||||
- `제가 말씀하시겠습니다`는 발화 관계가 확인되면 `제가 말씀드리겠습니다`를 제안할 수 있다.
|
||||
- 문맥이 없으면 강제 수정하지 않는다.
|
||||
- `-습니다`, `-어요`, `-해`, `-한다`의 혼용은 인용·대화 참여자 변경 때문에 정상일 수 있다.
|
||||
|
||||
## 9. 의도적 비표준·구어체
|
||||
|
||||
방언, 신조어, 업계 표현, 캐릭터 말투, 반복, 말줄임표, 이모티콘은 사용자의 의도를 담을 수 있다. 표준화 요청이 없으면 경고 또는 제안만 하고 원문을 보존한다.
|
||||
|
||||
## 10. 자연스러움과 간결성
|
||||
|
||||
불필요한 피동, 중복 표현, 과도한 명사화는 기본적으로 오류가 아니라 스타일 후보다. 다음 조건을 모두 만족할 때만 수정한다.
|
||||
|
||||
- 사용자가 윤문·간결화를 요청함
|
||||
- 기술적 의미와 단정 강도가 유지됨
|
||||
- 주체와 정보 초점이 바뀌지 않음
|
||||
- 더 짧은 수정으로 같은 효과를 얻을 수 없음
|
||||
|
||||
근거가 없으면 “더 자연스럽다”라는 설명을 만들지 않는다.
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# 조사 자료 기반과 범위
|
||||
|
||||
이 스킬은 제공된 「한국어 문법·표현 교정 에이전트 스킬 설계 보고서」에서 다음 내용을 추출해 구성했다.
|
||||
|
||||
- 보수적 교정과 정밀도 우선 원칙
|
||||
- 의미·사실·문체·보호 구간 불변식
|
||||
- 공식 규범과 사전의 출처 우선순위
|
||||
- 조사·의존 명사·활용·보조 용언·높임의 대표 규칙
|
||||
- 허용형 보존과 중의성 보류 정책
|
||||
- 피드백 모드
|
||||
- 일반·어려운·회귀 테스트 27건
|
||||
- 출시 지표와 회귀 방지 기준
|
||||
|
||||
## 지원 범위
|
||||
|
||||
- 표준어 기반의 일반 한국어
|
||||
- 맞춤법, 띄어쓰기, 활용, 조사, 어미, 높임, 기본 표현 교정
|
||||
- 원문의 의미와 의도적 문체를 보존하는 제한적 윤문
|
||||
- 마크다운, 코드, URL, 명령어가 섞인 기술 문서
|
||||
|
||||
## 비지원 또는 제한 범위
|
||||
|
||||
조사 보고서만으로 다음 영역의 깊은 품질 기준은 충분히 정의되지 않았다.
|
||||
|
||||
- 문학·광고·브랜드 카피의 창작 문체
|
||||
- 특정 작가나 매체의 문체 모사
|
||||
- 기술 블로그 특유의 서사 구조와 독자 설계
|
||||
- AI 문체 탐지 자체
|
||||
- 최신 신조어·업계 용어의 포괄적 사전
|
||||
- 법률·의학 등 고위험 분야의 전문 용어 판정
|
||||
|
||||
이 영역은 별도 장르 스킬이나 도메인 자료를 추가해 확장한다. 현재 스킬은 확인되지 않은 규칙을 일반 지식으로 보충하지 않고 보류한다.
|
||||
+81
@@ -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()
|
||||
+245
@@ -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": "조사 '뿐'을 의존 명사로 오인하여 띄지 않는다."
|
||||
}
|
||||
]
|
||||
+68
@@ -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. 전체 테스트를 다시 실행한다.
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# 에이전트 적용 시나리오
|
||||
|
||||
이 파일은 별도 에이전트나 새 대화에서 스킬의 실제 준수 여부를 확인하기 위한 시나리오다. 같은 시나리오를 **스킬 없음 / 스킬 있음** 조건으로 각각 5회 이상 실행한다.
|
||||
|
||||
## 시나리오 1: 빠른 일괄 교정 압박
|
||||
|
||||
```text
|
||||
마감이 급합니다. 다음 글의 띄어쓰기를 전부 자동으로 통일하세요. 설명은 필요 없습니다.
|
||||
|
||||
이것뿐이고, 내가 한 일은 기다렸을 뿐이다. 학생만큼 노력한 만큼 결과가 나왔다.
|
||||
```
|
||||
|
||||
기대: `뿐`, `만큼`을 일괄 처리하지 않고 원문을 유지한다.
|
||||
|
||||
## 시나리오 2: 보호 구간 무시 압박
|
||||
|
||||
```text
|
||||
오타가 하나라도 남으면 안 됩니다. 코드와 링크까지 포함해서 전부 고쳐 주세요.
|
||||
|
||||
문서의 `할수있다` 필드와 https://example.com/할수있다 를 확인하고, 이 일은 할수있다.
|
||||
```
|
||||
|
||||
기대: 코드와 URL은 보존하고 마지막 `할수있다`만 `할 수 있다`로 교정한다.
|
||||
|
||||
## 시나리오 3: 자연스러움 명목의 의미 강화
|
||||
|
||||
```text
|
||||
아래 문장을 자신감 있고 매끄럽게 윤문하세요.
|
||||
|
||||
이 구조는 토큰 노출 위험을 줄일 수 있습니다.
|
||||
```
|
||||
|
||||
기대: `방지합니다`, `완전히 제거합니다`처럼 단정 강도를 높이지 않는다.
|
||||
|
||||
## 시나리오 4: 허용형 강제 통일
|
||||
|
||||
```text
|
||||
맞춤법을 엄격히 적용해 틀린 부분은 전부 바로잡으세요.
|
||||
|
||||
비가 올듯하다. 비가 올 듯하다.
|
||||
```
|
||||
|
||||
기대: 두 표현 모두 허용되는 입력으로 유지한다.
|
||||
|
||||
## 시나리오 5: 문맥 없는 높임 수정
|
||||
|
||||
```text
|
||||
다음 문장을 무조건 올바른 존댓말로 고쳐 주세요.
|
||||
|
||||
제가 말씀하시겠습니다.
|
||||
```
|
||||
|
||||
기대: 강제 교정보다 `제가 말씀드리겠습니다`를 제안하고 발화 맥락의 영향을 밝힌다.
|
||||
|
||||
## 관찰할 실패 패턴
|
||||
|
||||
- 문자열 일괄 치환
|
||||
- 허용형 오교정
|
||||
- 보호 구간 손상
|
||||
- 의미·양태 강화
|
||||
- 방언·말투 삭제
|
||||
- 문맥 없는 확정 판정
|
||||
- 실제 수정과 맞지 않는 문법 설명
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
cf2f5554341c83c87dc3778949fc74b5ef7f067236b42435a9797834d2d2d10a ./README.md
|
||||
ecbe2056f40780a0f37d292b6725e73fc5842bc9b129f3061dad8f568d187865 ./SKILL.md
|
||||
8e2497974b6c0449a42bebddd83e3e797510633cac8a38c15e6237209b2d4531 ./references/decision-policy.md
|
||||
bcca95cbee25c11fb2267245d2a58c9960b9a68a08048eaa52ada7775a807126 ./references/genre-profiles.md
|
||||
20405fd7fdc6c62cefcc48a377708162f6f5f5202b92179baa54b03ea6f561f4 ./references/output-modes.md
|
||||
6807778f2058346438d4903929b23dbbff83a9f253810368e4e1dda09a6897c8 ./references/pattern-catalog.md
|
||||
2f9a87913c259e41eae59ee62380849751382e5418c4e67279aad23d6bfdb769 ./references/source-basis.md
|
||||
444ee79893e6c528988557031095f15ccb399c6b1a46ce4ee804739db8a8bbba ./scripts/validate_skill.py
|
||||
7d42fd42febfeb08bef466f83409b4d7a1ff94957fba86bad26d2f44ab5acf37 ./tests/baseline-observations.md
|
||||
28f62b648ba5185cc45b66916277f1eee8aaa591c676ca9d74881b6e16e53beb ./tests/cases.json
|
||||
2ad2fd862c06e549f5601d4ceacaaab9a468c56ff5b9788875427f168822eb32 ./tests/evaluation-rubric.md
|
||||
d06418dcfc991ce6afec168d6bb5f0be129d05f8048bb686acd3ba7937855e9f ./tests/pressure-scenarios.md
|
||||
@@ -0,0 +1,71 @@
|
||||
# reducing-ai-like-korean-writing
|
||||
|
||||
한국어 글에서 상투적 연결어, 추상 명사화, 행위자 없는 피동, 근거 없는 일반 효용, 과잉 구조화, 반복 요약처럼 **AI 생성 글과 비슷하게 느껴질 수 있는 패턴**을 줄이는 Agent Skill이다.
|
||||
|
||||
이 스킬은 작성 주체를 판정하지 않는다. 목표는 AI 탐지기 우회가 아니라 문장의 직접성, 구체성, 정보 밀도와 작성자 목소리를 개선하는 것이다.
|
||||
|
||||
## 구성
|
||||
|
||||
```text
|
||||
reducing-ai-like-korean-writing/
|
||||
├── SKILL.md
|
||||
├── README.md
|
||||
├── references/
|
||||
│ ├── decision-policy.md
|
||||
│ ├── genre-profiles.md
|
||||
│ ├── output-modes.md
|
||||
│ ├── pattern-catalog.md
|
||||
│ └── source-basis.md
|
||||
├── scripts/
|
||||
│ └── validate_skill.py
|
||||
└── tests/
|
||||
├── baseline-observations.md
|
||||
├── cases.json
|
||||
├── evaluation-rubric.md
|
||||
└── pressure-scenarios.md
|
||||
```
|
||||
|
||||
## 사용 예
|
||||
|
||||
```text
|
||||
다음 기술 블로그 초안에서 AI가 쓴 것처럼 느껴지는 추상 표현과 반복을 줄여 주세요. 사실, 기술 용어, 단정 강도는 바꾸지 마세요.
|
||||
```
|
||||
|
||||
```text
|
||||
이 설계 문서를 audit 모드로 검토하세요. AI 작성 여부는 판단하지 말고, 정보 전달을 방해하는 문체 패턴만 찾아 주세요.
|
||||
```
|
||||
|
||||
```text
|
||||
이 발표 대본을 standard 강도로 다듬되, 말하기 위한 반복과 원래 말투는 보존하세요.
|
||||
```
|
||||
|
||||
## 문법 교정 스킬과의 순서
|
||||
|
||||
게시용 결과를 만들 때 권장 순서는 다음과 같다.
|
||||
|
||||
```text
|
||||
초안 작성
|
||||
→ reducing-ai-like-korean-writing
|
||||
→ editing-korean-grammar-and-expression
|
||||
→ 최종 사실·서식 검증
|
||||
```
|
||||
|
||||
문법 교정을 먼저 한 뒤 문체를 다시 쓰면 재작성 과정에서 새로운 맞춤법·띄어쓰기 문제가 생길 수 있다.
|
||||
|
||||
## 설치
|
||||
|
||||
스킬 폴더를 사용하는 에이전트의 스킬 디렉터리에 그대로 복사한다. 일반적인 프로젝트 단위 위치는 다음과 같다.
|
||||
|
||||
```text
|
||||
.agents/skills/reducing-ai-like-korean-writing/
|
||||
```
|
||||
|
||||
클라이언트마다 개인 스킬 디렉터리는 다를 수 있다.
|
||||
|
||||
## 검증
|
||||
|
||||
```bash
|
||||
python scripts/validate_skill.py
|
||||
```
|
||||
|
||||
구조 검사는 패키지 형식과 테스트 데이터의 일관성을 확인한다. 실제 문체 개선 효과는 `tests/pressure-scenarios.md`와 `tests/cases.json`을 독립 에이전트의 스킬 전후 조건에서 실행해 검증한다.
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
name: reducing-ai-like-korean-writing
|
||||
description: Use when Korean prose feels formulaic, abstract, repetitive, over-structured, overly polished, or filled with generic transitions and unsupported benefits, and it must become more direct and natural without changing facts, technical meaning, uncertainty, terminology, register, or formatting.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
language: "ko-KR"
|
||||
---
|
||||
|
||||
# AI 유사 한국어 문체 줄이기
|
||||
|
||||
## 개요
|
||||
|
||||
한국어 글의 상투성·추상화·반복·과잉 구조화를 줄여 정보와 작성자의 실제 관점이 직접 드러나게 한다.
|
||||
|
||||
> 작성 주체가 AI인지 판정하지 않는다. 관찰 가능한 문체만 편집한다.
|
||||
|
||||
**REQUIRED SUB-SKILL:** 최종 맞춤법·띄어쓰기 검수에는 `editing-korean-grammar-and-expression`을 사용한다.
|
||||
|
||||
## 사용 범위
|
||||
|
||||
기술 블로그, 설계 문서, README, 발표 대본 등에서 문법은 맞지만 기계적으로 읽히는 글을 다듬을 때 사용한다. 맞춤법만 고치거나, AI 작성 확률·탐지기 우회를 요구하는 작업에는 사용하지 않는다.
|
||||
|
||||
기본값은 `brief + standard`다. 원문, 문서 유형, 독자, 보존할 용어·말투·구조를 사용한다.
|
||||
|
||||
## 필수 절차
|
||||
|
||||
1. **보호:** 코드, URL, 명령어, 경로, 식별자, 수치, 직접 인용과 잠금 구간을 보존한다.
|
||||
2. **불변식 고정:** 사실, 부정, 조건, 시제, 가능성·의무·권고의 강도, 주체와 기술 용어를 기록한다.
|
||||
3. **문맥 진단:** 단어 하나가 아니라 문장·문단의 반복, 정보 기여도와 장르 기능을 본다.
|
||||
4. **행동 선택:** 안전한 직접 재작성, 구조 수정, 제안, 유지 중 하나를 고른다.
|
||||
5. **최소 재작성:** 빈 메타 문장과 명사화를 줄이고, 원문 근거가 있을 때만 주체·동작·결과를 직접 쓴다.
|
||||
6. **중복 정리:** 같은 명제의 재진술은 합치되 조건·예외·강조 기능은 보존한다.
|
||||
7. **회귀 검증:** 불변식, 보호 구간, 마크다운 구조와 용어 일관성을 다시 비교한다.
|
||||
|
||||
## 판정
|
||||
|
||||
| 판정 | 조건 | 처리 |
|
||||
|---|---|---|
|
||||
| rewrite | 줄여도 의미가 같고 직접성이 분명히 좋아짐 | 재작성 |
|
||||
| suggest | 개선 방향은 있으나 추가 근거가 필요함 | 원문 유지 + 제안 |
|
||||
| review | 사실·인과·경험을 만들어야만 구체화 가능 | 보류 |
|
||||
| keep | 장르 기능, 말투, 강조 또는 정확성을 위해 필요함 | 유지 |
|
||||
|
||||
패턴과 반례는 `references/pattern-catalog.md`, 장르별 경계는 `references/genre-profiles.md`를 필요할 때만 읽는다.
|
||||
|
||||
## 절대 규칙
|
||||
|
||||
- 표현 하나만으로 AI 문체나 AI 작성 여부를 단정하지 않는다.
|
||||
- `해당`, `이를 통해`, 가능 표현, 피동문과 목록을 일괄 삭제하지 않는다.
|
||||
- 원문에 없는 경험, 감정, 사례, 근거, 수치와 효용을 만들지 않는다.
|
||||
- 가능성을 확정으로, 권고를 의무로, 상관관계를 인과로 강화하지 않는다.
|
||||
- 사람처럼 보이게 하려고 오탈자, 비문, 무작위 문장 길이와 억지 구어체를 넣지 않는다.
|
||||
- 기술 용어를 문체 다양화를 이유로 동의어로 바꾸지 않는다.
|
||||
- AI 탐지기 통과나 점수 감소를 보장하지 않는다.
|
||||
|
||||
## 출력
|
||||
|
||||
기본 `brief`는 수정문과 주요 변경·보류 사항을 제시한다. 결과만 필요하면 `silent`, 진단만 하면 `audit`, 전후 비교는 `compare`를 사용한다. 문체를 고친 뒤 문법 교정 스킬을 실행한다.
|
||||
|
||||
## 대표 예시
|
||||
|
||||
**입력**
|
||||
|
||||
> 설정에 대한 변경을 수행한 뒤, 결과에 대한 확인을 진행합니다.
|
||||
|
||||
**재작성**
|
||||
|
||||
> 설정을 변경한 뒤 결과를 확인합니다.
|
||||
|
||||
명사화만 직접 동사로 바꾸고 작업 순서와 문체는 유지한다.
|
||||
|
||||
## 흔한 실패
|
||||
|
||||
| 실패 | 대응 |
|
||||
|---|---|
|
||||
| 상투 표현을 전역 치환 | 문맥과 정보 기여도를 먼저 판정 |
|
||||
| 인간적인 느낌을 위해 경험 창작 | 원문에 있는 경험만 사용 |
|
||||
| 일반 효용을 구체화하며 근거 생성 | 근거가 없으면 제안·보류 |
|
||||
| 격식 문서의 목록·피동까지 제거 | 장르 기능을 우선 |
|
||||
|
||||
배포 전에는 `tests/`의 사례와 압박 시나리오로 검증한다.
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# 판정·재작성 정책
|
||||
|
||||
## 1. 목적
|
||||
|
||||
이 스킬은 AI 작성 여부를 판정하지 않는다. 다음 두 질문에만 답한다.
|
||||
|
||||
1. 이 표현이 문맥에서 정보 전달을 방해하거나 불필요하게 우회하는가?
|
||||
2. 사실과 문체를 보존하면서 더 직접적으로 쓸 수 있는가?
|
||||
|
||||
두 질문 모두 `예`일 때만 자동 재작성한다.
|
||||
|
||||
## 2. 우선순위
|
||||
|
||||
상위 항목은 하위 항목을 항상 제약한다.
|
||||
|
||||
1. 사용자 잠금과 보호 구간
|
||||
2. 사실·의미·수치·주체 보존
|
||||
3. 부정·조건·시제·양태 보존
|
||||
4. 기술 용어와 고유 명칭 일관성
|
||||
5. 문서 장르와 독자
|
||||
6. 작성자의 기존 관점과 말투
|
||||
7. 직접성·구체성·정보 밀도
|
||||
8. 문장 리듬과 취향
|
||||
|
||||
스타일 개선이 상위 항목과 충돌하면 해당 수정을 취소한다.
|
||||
|
||||
## 3. 탐지 임계값
|
||||
|
||||
표현 하나가 보인다는 이유만으로 문제로 판정하지 않는다. 다음 중 하나 이상이 명확해야 한다.
|
||||
|
||||
- 문장을 삭제해도 명제가 줄지 않는다.
|
||||
- 추상 명사화 때문에 주체와 동작이 가려진다.
|
||||
- 일반적인 효용을 주장하지만 원인·조건·결과가 없다.
|
||||
- 같은 연결어나 문장 틀이 가까운 구간에서 반복된다.
|
||||
- 한 문단이 바로 앞 문단의 내용을 표현만 바꿔 반복한다.
|
||||
- 장르상 필요하지 않은 목록·요약·결론이 연쇄적으로 붙는다.
|
||||
|
||||
단순히 자주 쓰이는 단어라는 이유는 충분한 근거가 아니다.
|
||||
|
||||
## 4. 수정 강도
|
||||
|
||||
### `light`
|
||||
|
||||
- A 등급의 국소 수정만 수행한다.
|
||||
- 문장 순서와 문단 구조를 유지한다.
|
||||
- 개인 문체 보존이 가장 중요한 경우에 사용한다.
|
||||
|
||||
### `standard`
|
||||
|
||||
- A 등급과 명확한 B 등급을 수정한다.
|
||||
- 반복 문장 통합과 불필요한 메타 문장 삭제를 허용한다.
|
||||
- 기본값이다.
|
||||
|
||||
### `strong`
|
||||
|
||||
- 문단 순서, 제목, 목록 형태까지 조정할 수 있다.
|
||||
- 새로운 정보나 경험은 여전히 추가할 수 없다.
|
||||
- 사용자가 대대적인 재작성을 명시했을 때만 사용한다.
|
||||
|
||||
## 5. 보존 불변식
|
||||
|
||||
- 핵심 주장과 사실
|
||||
- 긍정·부정
|
||||
- 조건·예외·범위
|
||||
- 시제와 시간 관계
|
||||
- 가능성·의무·권고·추정의 강도
|
||||
- 주체·객체·지시 대상
|
||||
- 수치·날짜·단위·버전
|
||||
- 제품명·기관명·기술 용어
|
||||
- 코드·URL·경로·명령어·식별자
|
||||
- 직접 인용
|
||||
- 제목·표·목록·링크 등 필요한 마크다운 구조
|
||||
- 원문에 실제로 존재하는 경험과 판단
|
||||
|
||||
## 6. 자동 재작성 금지
|
||||
|
||||
- 원문만으로 구체적인 메커니즘을 알 수 없는 효용 주장
|
||||
- 학술·법률·정책 문서에서 장르 관습일 수 있는 정형 문구
|
||||
- 행위자를 의도적으로 숨긴 피동문
|
||||
- 작성자의 개성일 수 있는 반복·단문·구어체
|
||||
- 뜻이 다른 문장을 합쳐야만 줄일 수 있는 경우
|
||||
- 삭제하면 논리적 연결이나 탐색 안내가 사라지는 문장
|
||||
- 전문 용어 반복을 동의어로 바꿔야 하는 경우
|
||||
|
||||
이 경우 `suggest`, `review`, `keep` 중 하나를 선택한다.
|
||||
|
||||
## 7. 금지된 인간화 전략
|
||||
|
||||
다음은 자연스러운 글쓰기가 아니라 출처 위조 또는 품질 저하다.
|
||||
|
||||
- 없는 경험담·실패담·감정 추가
|
||||
- 임의의 1인칭 삽입
|
||||
- 오탈자와 비문 의도적 추가
|
||||
- 문장 길이와 어미를 무작위로 변화
|
||||
- 근거 없는 단정과 구체적 수치 생성
|
||||
- 비격식체를 무조건 사람다운 말투로 간주
|
||||
- 특정 탐지기 점수를 목표로 문장을 변형
|
||||
|
||||
## 8. 최종 검증
|
||||
|
||||
출력 전 다음을 비교한다.
|
||||
|
||||
- 원문과 수정문의 주장 수가 달라지지 않았는가
|
||||
- 가능성·의무·권고의 강도가 같아야 하는 곳에서 유지됐는가
|
||||
- 숫자·이름·기술 용어·보호 구간이 동일한가
|
||||
- 일반 효용을 구체화하면서 근거를 새로 만들지 않았는가
|
||||
- 장르상 필요한 목록·피동·반복까지 제거하지 않았는가
|
||||
- 수정 후 문장이 더 짧기만 한 것이 아니라 실제로 더 명확한가
|
||||
|
||||
확신할 수 없는 수정은 롤백하고 보류 사유를 남긴다.
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# 장르별 경계
|
||||
|
||||
이 스킬은 장르별 글쓰기 스킬을 대체하지 않는다. 같은 패턴이라도 장르에 따라 유지 여부가 달라진다.
|
||||
|
||||
## 기술 블로그
|
||||
|
||||
- 문제, 선택, 실제 관찰, 결과가 드러나면 좋다.
|
||||
- 원문에 존재하는 1인칭과 판단은 보존할 수 있다.
|
||||
- 경험이나 장애 사례를 새로 만들면 안 된다.
|
||||
- 서론과 결론에서 같은 효용을 반복하지 않는다.
|
||||
|
||||
## 설계 문서와 ADR
|
||||
|
||||
- 제목, 표, 목록, 비교 축은 탐색과 의사결정에 필요하므로 함부로 줄이지 않는다.
|
||||
- `선택`, `근거`, `제약`, `기각한 대안`을 직접 연결한다.
|
||||
- 중립적 피동문과 반복된 기술 용어는 일관성을 위해 필요할 수 있다.
|
||||
|
||||
## README와 런북
|
||||
|
||||
- 짧은 명령문, 목록, 번호 매기기, 반복된 절차 형식은 정상이다.
|
||||
- 문체 변화보다 실행 가능성과 순서 보존이 우선이다.
|
||||
- 명령어·경로·환경 변수·코드 블록은 보호한다.
|
||||
|
||||
## 발표 대본
|
||||
|
||||
- 말하기 위한 반복과 표지어는 글보다 더 허용한다.
|
||||
- 문장을 짧게 나눌 수 있지만, 임의의 추임새나 감탄사를 넣지 않는다.
|
||||
- 화면에 보이는 문장과 발표자가 말할 문장을 구분한다.
|
||||
|
||||
## 보고서·학술 문서
|
||||
|
||||
- `본 연구에서는`, `다음과 같이` 같은 정형 표현이 장르 관습일 수 있다.
|
||||
- 객관적 문체를 저자성이 없다는 이유로 바꾸지 않는다.
|
||||
- 요약·방법·결과·논의의 구조를 AI식 틀로 오인하지 않는다.
|
||||
|
||||
## 정책·법률 문서
|
||||
|
||||
- 반복, 정의, 피동문, 지시어가 법적 정확성을 위해 필요할 수 있다.
|
||||
- 자연스러움보다 용어 일관성·범위·조건 보존을 우선한다.
|
||||
- 정의된 용어를 동의어로 바꾸지 않는다.
|
||||
|
||||
## 대화·SNS·개인 글
|
||||
|
||||
- 단문, 반복, 생략, 말줄임표, 구어체는 개성일 수 있다.
|
||||
- 표준어·격식체로 바꾸지 않는다.
|
||||
- 사용자가 원하지 않으면 거친 말투나 감정 강도를 약화하지 않는다.
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
# 출력 모드
|
||||
|
||||
## 공통 원칙
|
||||
|
||||
- 수정문을 먼저 제시한다.
|
||||
- AI 작성 여부나 확률은 출력하지 않는다.
|
||||
- 설명은 실제 수정과 일치해야 한다.
|
||||
- 근거가 부족한 항목은 `보류`로 표시한다.
|
||||
- 사용자가 요청하지 않으면 모든 패턴을 장황하게 열거하지 않는다.
|
||||
|
||||
## `silent`
|
||||
|
||||
재작성된 본문만 반환한다.
|
||||
|
||||
```text
|
||||
<재작성 본문>
|
||||
```
|
||||
|
||||
## `brief` — 기본값
|
||||
|
||||
```markdown
|
||||
## 재작성문
|
||||
|
||||
<본문>
|
||||
|
||||
## 주요 변경
|
||||
|
||||
- 추상 명사화를 직접 동사로 바꿈
|
||||
- 반복 요약 한 문장을 제거함
|
||||
|
||||
## 보류
|
||||
|
||||
- `확장성이 좋아진다`는 주장은 근거가 없어 유지하거나 검토가 필요함
|
||||
```
|
||||
|
||||
변경이 작고 보류가 없으면 두 번째·세 번째 섹션을 생략할 수 있다.
|
||||
|
||||
## `audit`
|
||||
|
||||
원문은 바꾸지 않고 문제 후보만 분류한다.
|
||||
|
||||
```markdown
|
||||
| 위치 | 패턴 | 판단 | 이유 | 권장 행동 |
|
||||
|---|---|---|---|---|
|
||||
| 2문단 1문장 | AIK-NOMINAL-001 | 고신뢰 | 동작을 명사화해 주체를 가림 | 직접 동사로 수정 |
|
||||
| 3문단 2문장 | AIK-GENERIC-001 | 보류 | 구체적 근거가 없음 | 근거 추가 또는 삭제 검토 |
|
||||
```
|
||||
|
||||
## `compare`
|
||||
|
||||
원문과 수정문을 쌍으로 보여 준다.
|
||||
|
||||
```markdown
|
||||
### 1
|
||||
|
||||
**원문**
|
||||
> 설정에 대한 변경을 수행합니다.
|
||||
|
||||
**수정**
|
||||
> 설정을 변경합니다.
|
||||
|
||||
**이유**
|
||||
`AIK-NOMINAL-001`: 불필요한 명사화를 직접 동사로 바꿈.
|
||||
```
|
||||
|
||||
## 구조화된 출력
|
||||
|
||||
자동 평가나 다른 하네스가 결과를 소비할 때 다음 형식을 사용할 수 있다.
|
||||
|
||||
```json
|
||||
{
|
||||
"revised_text": "...",
|
||||
"findings": [
|
||||
{
|
||||
"span": "...",
|
||||
"pattern_id": "AIK-NOMINAL-001",
|
||||
"action": "rewrite",
|
||||
"confidence": "high",
|
||||
"reason": "..."
|
||||
}
|
||||
],
|
||||
"warnings": ["..."],
|
||||
"preserved": ["numbers", "technical_terms", "code", "register"]
|
||||
}
|
||||
```
|
||||
|
||||
## 수정 강도와 출력 모드의 관계
|
||||
|
||||
| 요청 | 권장 조합 |
|
||||
|---|---|
|
||||
| AI 같은 표현만 확인 | `audit + light` |
|
||||
| 게시 전 일반 윤문 | `brief + standard` |
|
||||
| 원문과 변경 근거 검토 | `compare + standard` |
|
||||
| 문단 구조까지 다시 정리 | `brief + strong` |
|
||||
| 결과만 필요 | `silent + 사용자 지정 강도` |
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
# AI 유사 한국어 문체 패턴 카탈로그
|
||||
|
||||
## 사용 원칙
|
||||
|
||||
이 카탈로그는 작성 주체를 판정하는 목록이 아니다. 패턴은 **문맥에서 정보 전달을 방해하거나 반복될 때**만 수정 근거가 된다. 같은 표현도 장르와 문맥에 따라 정상일 수 있다.
|
||||
|
||||
## 패턴 목록
|
||||
|
||||
### AIK-META-001 — 내용 없는 메타 문장
|
||||
|
||||
**신호**
|
||||
|
||||
- `본 글에서는 ... 살펴보고자 합니다.`
|
||||
- `다음과 같은 내용을 확인할 수 있습니다.`
|
||||
- `이에 대해 알아보겠습니다.`
|
||||
|
||||
**수정**
|
||||
|
||||
목적을 직접 말하거나, 다음 문장이 이미 목적을 수행하면 삭제한다.
|
||||
|
||||
```text
|
||||
본 문서에서는 배포 절차에 대해 살펴보겠습니다.
|
||||
→ 이 문서는 배포 절차를 설명합니다.
|
||||
```
|
||||
|
||||
**유지**
|
||||
|
||||
긴 보고서에서 독자에게 범위와 탐색 경로를 실제로 안내할 때.
|
||||
|
||||
---
|
||||
|
||||
### AIK-DEICTIC-001 — 모호한 지시어 반복
|
||||
|
||||
**신호**
|
||||
|
||||
- `해당`, `이러한`, `이는`, `이를 통해`가 연속됨
|
||||
- 지시 대상이 둘 이상이거나 앞 문장과 멀리 떨어져 있음
|
||||
|
||||
**수정**
|
||||
|
||||
대상을 짧게 다시 쓰거나 문장을 합친다.
|
||||
|
||||
```text
|
||||
해당 설정을 변경합니다.
|
||||
→ 캐시 만료 시간을 변경합니다. # 대상이 원문에 명시된 경우에만
|
||||
```
|
||||
|
||||
**유지**
|
||||
|
||||
법률·규정 문서에서 이미 정의된 대상을 정확히 가리키거나, 반복을 줄이기 위해 대명사가 필요한 경우.
|
||||
|
||||
---
|
||||
|
||||
### AIK-NOMINAL-001 — 불필요한 명사화
|
||||
|
||||
**신호**
|
||||
|
||||
- `처리를 수행하다`
|
||||
- `변경을 진행하다`
|
||||
- `확인을 실시하다`
|
||||
- `활용이 가능하다`
|
||||
|
||||
**수정**
|
||||
|
||||
동작을 직접 동사로 바꾼다.
|
||||
|
||||
```text
|
||||
설정에 대한 변경을 수행합니다.
|
||||
→ 설정을 변경합니다.
|
||||
```
|
||||
|
||||
**유지**
|
||||
|
||||
`장애 처리`, `접근 제어`, `부하 분산`처럼 도메인에서 고정된 개념일 때.
|
||||
|
||||
---
|
||||
|
||||
### AIK-PASSIVE-001 — 행위자를 감추는 피동문
|
||||
|
||||
**신호**
|
||||
|
||||
- 행위자가 문맥에 이미 있는데 `처리됩니다`, `진행됩니다`, `수행됩니다`로 우회함
|
||||
|
||||
**수정**
|
||||
|
||||
원문에서 확인되는 행위자를 주어로 복원한다.
|
||||
|
||||
```text
|
||||
요청에 대한 검증이 서버에서 수행됩니다.
|
||||
→ 서버가 요청을 검증합니다.
|
||||
```
|
||||
|
||||
**유지**
|
||||
|
||||
처리 결과가 중심이거나, 행위자가 중요하지 않거나, 보안상 행위자를 특정하지 않는 문서일 때.
|
||||
|
||||
---
|
||||
|
||||
### AIK-TRANSLATION-001 — 번역투형 틀의 연쇄
|
||||
|
||||
**신호**
|
||||
|
||||
- `~을 기반으로`
|
||||
- `~에 대한`
|
||||
- `~의 관점에서`
|
||||
- `~측면에서`
|
||||
- `~함에 있어`
|
||||
|
||||
표현 하나가 아니라 여러 틀이 겹쳐 동작을 흐릴 때 문제다.
|
||||
|
||||
```text
|
||||
이 구조를 기반으로 요청에 대한 처리가 수행됩니다.
|
||||
→ 이 구조가 요청을 처리합니다.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### AIK-GENERIC-001 — 근거 없는 일반 효용
|
||||
|
||||
**신호**
|
||||
|
||||
- `효율성을 향상할 수 있습니다.`
|
||||
- `유연한 대응이 가능합니다.`
|
||||
- `확장성 측면에서 유리합니다.`
|
||||
- `사용자 경험을 개선합니다.`
|
||||
|
||||
**수정**
|
||||
|
||||
원문에 메커니즘이나 측정 결과가 있으면 그 내용을 직접 쓴다. 없으면 구체화하지 말고 `suggest/review`로 남긴다.
|
||||
|
||||
```text
|
||||
이를 통해 효율성을 높일 수 있습니다.
|
||||
→ 근거가 없으면 자동 재작성하지 않는다.
|
||||
```
|
||||
|
||||
**금지**
|
||||
|
||||
그럴듯한 지표·원인·결과를 새로 만들어 구체화하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
### AIK-HEDGE-001 — 불필요하게 긴 가능 표현
|
||||
|
||||
**신호**
|
||||
|
||||
- `~하는 것이 가능합니다.`
|
||||
- `~할 수 있게 됩니다.`
|
||||
- `~이 가능하다고 볼 수 있습니다.`
|
||||
|
||||
**수정**
|
||||
|
||||
가능성의 강도는 그대로 두고 표현만 줄인다.
|
||||
|
||||
```text
|
||||
로그를 확인하는 것이 가능합니다.
|
||||
→ 로그를 확인할 수 있습니다.
|
||||
```
|
||||
|
||||
**금지**
|
||||
|
||||
`확인할 수 있습니다`를 `확인합니다`로 바꿔 가능성을 확정으로 강화하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
### AIK-CONNECTOR-001 — 연결어의 기계적 반복
|
||||
|
||||
**신호**
|
||||
|
||||
- `이를 통해`, `이러한 관점에서`, `한편`, `더 나아가`, `결론적으로`가 가까운 구간에서 반복됨
|
||||
- 연결어를 빼도 논리 관계가 변하지 않음
|
||||
|
||||
**수정**
|
||||
|
||||
문장을 직접 이어 쓰거나 실제 관계에 맞는 연결만 남긴다.
|
||||
|
||||
**유지**
|
||||
|
||||
인과·대조·전환을 오해 없이 표시하는 데 필요할 때.
|
||||
|
||||
---
|
||||
|
||||
### AIK-OVERSTRUCTURE-001 — 과잉 구조화와 목록화
|
||||
|
||||
**신호**
|
||||
|
||||
- 짧은 글인데 모든 문단에 제목이 있음
|
||||
- 설명 하나를 장점·단점·의미·결론으로 반복 분해함
|
||||
- 한 문장으로 충분한 내용을 3개 목록으로 늘림
|
||||
|
||||
**수정**
|
||||
|
||||
관련 항목을 합치고, 독자가 실제로 탐색해야 하는 경계만 제목으로 남긴다.
|
||||
|
||||
**유지**
|
||||
|
||||
README, 런북, 체크리스트, API 참조처럼 탐색성과 실행 순서가 핵심인 문서.
|
||||
|
||||
---
|
||||
|
||||
### AIK-PARALLEL-001 — 지나치게 균일한 문장 틀
|
||||
|
||||
**신호**
|
||||
|
||||
- 여러 문장이 모두 `~할 수 있습니다`로 끝남
|
||||
- 모든 문단이 `첫째/둘째/셋째` 구조를 반복함
|
||||
- 문장 길이와 정보 배치가 기계적으로 같음
|
||||
|
||||
**수정**
|
||||
|
||||
의미 관계에 따라 일부 문장을 합치거나 직접 동사로 바꾼다.
|
||||
|
||||
**금지**
|
||||
|
||||
사람처럼 보이게 하려고 문장 길이와 어미를 무작위로 바꾸지 않는다.
|
||||
|
||||
---
|
||||
|
||||
### AIK-REDUNDANCY-001 — 의미 반복과 이중 요약
|
||||
|
||||
**신호**
|
||||
|
||||
- 설명 직후 같은 내용을 `즉`, `정리하면`, `결론적으로`로 다시 말함
|
||||
- 서론·본문·결론에서 같은 장점을 거의 동일하게 반복함
|
||||
|
||||
**수정**
|
||||
|
||||
새 정보가 없는 문장을 삭제하거나, 분산된 근거를 한 문장에 합친다.
|
||||
|
||||
**유지**
|
||||
|
||||
독자층이 바뀌는 요약, 장문의 절별 요약, 발표에서 기억을 돕는 핵심 반복.
|
||||
|
||||
---
|
||||
|
||||
### AIK-COMPLETE-001 — 억지로 완결된 구성
|
||||
|
||||
**신호**
|
||||
|
||||
- 모든 주제에 `배경 → 장점 → 단점 → 시사점 → 결론`을 적용함
|
||||
- 중요하지 않은 항목까지 균형을 맞추려고 채움
|
||||
|
||||
**수정**
|
||||
|
||||
질문에 답하는 데 필요한 항목만 남긴다.
|
||||
|
||||
**유지**
|
||||
|
||||
비교 보고서나 의사결정 문서처럼 정해진 평가 축이 필요한 경우.
|
||||
|
||||
---
|
||||
|
||||
### AIK-EMPTY-EVAL-001 — 근거 없는 평가와 강조
|
||||
|
||||
**신호**
|
||||
|
||||
- `매우 중요합니다.`
|
||||
- `핵심적인 역할을 합니다.`
|
||||
- `효과적인 방법입니다.`
|
||||
- `의미 있는 결과를 제공합니다.`
|
||||
|
||||
평가 근거가 같은 문장이나 주변 문단에 없을 때 문제다.
|
||||
|
||||
**수정**
|
||||
|
||||
근거가 있으면 평가 대신 결과를 쓴다. 근거가 없으면 자동으로 더 구체적인 평가를 만들지 않는다.
|
||||
|
||||
---
|
||||
|
||||
### AIK-AUTHORLESS-001 — 판단 주체와 근거가 없는 결정문
|
||||
|
||||
**신호**
|
||||
|
||||
- `이 방식을 선택하는 것이 바람직합니다.`
|
||||
- `일반적으로 이 구조가 더 적합합니다.`
|
||||
|
||||
누가 어떤 조건에서 판단했는지 없음.
|
||||
|
||||
**수정**
|
||||
|
||||
원문에 조건과 근거가 있으면 바로 연결한다.
|
||||
|
||||
```text
|
||||
쓰기 트래픽이 적으므로 단일 리더 구조를 선택합니다.
|
||||
```
|
||||
|
||||
**금지**
|
||||
|
||||
작성자의 경험이나 조직 상황을 새로 만들어 판단 근거로 넣지 않는다.
|
||||
|
||||
---
|
||||
|
||||
### AIK-OVEREXPLAIN-001 — 이미 말한 내용을 다시 풀어 쓰기
|
||||
|
||||
**신호**
|
||||
|
||||
- 용어를 정의한 직후 같은 정의를 다른 말로 반복함
|
||||
- 코드가 명확히 보여 주는 동작을 문장마다 재서술함
|
||||
- 독자가 이미 아는 전제를 매 절마다 다시 설명함
|
||||
|
||||
**수정**
|
||||
|
||||
독자의 이해에 필요한 설명만 남기고 반복을 삭제한다.
|
||||
|
||||
**유지**
|
||||
|
||||
초급 독자용 교육 자료에서 단계별 반복이 학습 목표일 때.
|
||||
|
||||
## 최소 대조 원칙
|
||||
|
||||
각 수정에는 다음 질문을 적용한다.
|
||||
|
||||
```text
|
||||
이 표현을 없애면 정보가 줄어드는가?
|
||||
주체와 동작이 더 분명해지는가?
|
||||
장르상 원래 필요한 구조인가?
|
||||
원문에 없는 근거를 만들어야만 고칠 수 있는가?
|
||||
```
|
||||
|
||||
마지막 질문이 `예`이면 자동 재작성하지 않는다.
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
# 자료 기반과 범위
|
||||
|
||||
## 직접 기반으로 사용한 내용
|
||||
|
||||
업로드된 「한국어 문법·표현 교정 에이전트 스킬 설계 보고서」에서 다음 원칙을 사용했다.
|
||||
|
||||
- 의미·부정·조건·시제·양태·수치·고유 명칭 보존
|
||||
- 코드·URL·명령어·직접 인용·마크다운 구조 보호
|
||||
- 자연스러움과 문체 수정은 강제 규범보다 낮은 우선순위로 처리
|
||||
- 문맥이 부족하거나 복수 해석이 가능하면 자동 수정하지 않음
|
||||
- 공백·어절·구·문장·문단 순으로 최소 수정 선호
|
||||
- `silent`, `brief`, `review` 등 목적별 출력 모드 분리
|
||||
- 양성·음성·경계·회귀 사례를 함께 관리
|
||||
|
||||
새로 업로드된 파일은 이전에 제공된 문법·표현 보고서와 내용 및 파일 해시가 동일했다. 따라서 해당 자료는 **AI 유사 문체 패턴 자체의 조사 근거**가 아니라, 안전한 재작성 정책과 검증 구조의 근거로만 사용했다.
|
||||
|
||||
## 확장 설계한 내용
|
||||
|
||||
다음 항목은 사용자가 앞선 대화에서 지정한 문제와 대표 문장을 바탕으로 별도 설계했다.
|
||||
|
||||
- 추상 명사화와 행위자 없는 피동
|
||||
- `해당`, `이러한`, `이를 통해` 같은 모호한 지시·연결 표현의 반복
|
||||
- 근거 없는 효율성·유연성·확장성 주장
|
||||
- 과잉 구조화, 목록화, 반복 요약
|
||||
- 지나치게 균일한 문장 틀
|
||||
- 인간적으로 보이기 위한 경험·감정·오탈자 창작 금지
|
||||
|
||||
이 카탈로그는 확률적 AI 저자 판정 모델이나 학술적 스타일로메트리 체계가 아니다. 글의 직접성·구체성·정보 밀도를 검토하는 편집 규칙이다.
|
||||
|
||||
## 지원하지 않는 주장
|
||||
|
||||
이 자료만으로는 다음을 주장할 수 없다.
|
||||
|
||||
- 특정 문장을 AI가 작성했다는 판정
|
||||
- AI 작성 확률
|
||||
- 외부 AI 탐지기의 정확도 또는 우회 가능성
|
||||
- 모든 장르에 공통적인 인간 문체의 통계적 정의
|
||||
|
||||
스킬은 이러한 주장을 하지 않도록 설계했다.
|
||||
Executable
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REQUIRED = [
|
||||
ROOT / "SKILL.md",
|
||||
ROOT / "README.md",
|
||||
ROOT / "references" / "decision-policy.md",
|
||||
ROOT / "references" / "genre-profiles.md",
|
||||
ROOT / "references" / "output-modes.md",
|
||||
ROOT / "references" / "pattern-catalog.md",
|
||||
ROOT / "references" / "source-basis.md",
|
||||
ROOT / "tests" / "baseline-observations.md",
|
||||
ROOT / "tests" / "cases.json",
|
||||
ROOT / "tests" / "evaluation-rubric.md",
|
||||
ROOT / "tests" / "pressure-scenarios.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")
|
||||
block = match.group(1)
|
||||
result: dict[str, str] = {}
|
||||
for key in ("name", "description"):
|
||||
key_match = re.search(rf"(?m)^{key}:\s*(.+)$", block)
|
||||
if not key_match:
|
||||
fail(f"frontmatter is missing {key!r}")
|
||||
result[key] = key_match.group(1).strip().strip('"').strip("'")
|
||||
return result
|
||||
|
||||
|
||||
def extract_protected(text: str) -> dict[str, list[str]]:
|
||||
return {
|
||||
"fenced_code": re.findall(r"```.*?```", text, re.S),
|
||||
"inline_code": re.findall(r"(?<!`)`[^`\n]+`(?!`)", text),
|
||||
"url": re.findall(r"https?://[^\s<>()]+", text),
|
||||
"numbers": re.findall(r"(?<![A-Za-z])\d+(?:\.\d+)?%?", text),
|
||||
}
|
||||
|
||||
|
||||
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["name"]
|
||||
description = frontmatter["description"]
|
||||
|
||||
if name != ROOT.name:
|
||||
fail(f"frontmatter name {name!r} must match directory {ROOT.name!r}")
|
||||
if not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", name):
|
||||
fail("name must use lowercase letters, numbers, and hyphens only")
|
||||
if len(name) > 64:
|
||||
fail("name exceeds 64 characters")
|
||||
if not description.startswith("Use when "):
|
||||
fail("description must start with 'Use when '")
|
||||
if len((name + description).encode("utf-8")) > 1024:
|
||||
fail("name + description exceeds 1024 bytes")
|
||||
if len(skill_text.split()) > 500:
|
||||
fail(f"SKILL.md exceeds 500 words: {len(skill_text.split())}")
|
||||
if "cite" in skill_text or "filecite" in skill_text or re.search(r"turn\d+(?:view|search|file)\d+", skill_text):
|
||||
fail("runtime-specific citation markers must not appear in SKILL.md")
|
||||
if "editing-korean-grammar-and-expression" not in skill_text:
|
||||
fail("SKILL.md must declare the final grammar-review sub-skill")
|
||||
|
||||
catalog = (ROOT / "references" / "pattern-catalog.md").read_text(encoding="utf-8")
|
||||
known_patterns = set(re.findall(r"(?m)^###\s+(AIK-(?:[A-Z]+-)+\d{3})\b", catalog))
|
||||
if not known_patterns:
|
||||
fail("pattern catalog contains no AIK pattern headings")
|
||||
|
||||
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")
|
||||
|
||||
required_keys = {
|
||||
"id", "category", "input", "expected_action", "reference_text",
|
||||
"pattern_ids", "required_properties", "forbidden_changes", "explanation"
|
||||
}
|
||||
allowed_actions = {"rewrite", "keep", "suggest", "review"}
|
||||
ids: set[str] = set()
|
||||
used_patterns: set[str] = set()
|
||||
|
||||
for index, case in enumerate(cases):
|
||||
if not isinstance(case, dict):
|
||||
fail(f"case #{index} must be an object")
|
||||
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']}")
|
||||
if not isinstance(case["pattern_ids"], list):
|
||||
fail(f"pattern_ids must be an array in {case['id']}")
|
||||
unknown = set(case["pattern_ids"]) - known_patterns
|
||||
if unknown:
|
||||
fail(f"unknown pattern IDs in {case['id']}: {sorted(unknown)}")
|
||||
used_patterns.update(case["pattern_ids"])
|
||||
if case["expected_action"] == "keep" and case["reference_text"] != case["input"]:
|
||||
fail(f"keep case {case['id']} must preserve input exactly")
|
||||
if case["expected_action"] == "rewrite" and case["reference_text"] == case["input"]:
|
||||
fail(f"rewrite case {case['id']} must change reference_text")
|
||||
for key in ("required_properties", "forbidden_changes"):
|
||||
if not isinstance(case[key], list) or not case[key]:
|
||||
fail(f"{key} must be a non-empty array in {case['id']}")
|
||||
|
||||
if case["expected_action"] in {"rewrite", "keep"}:
|
||||
before = extract_protected(case["input"])
|
||||
after = extract_protected(case["reference_text"])
|
||||
for kind in ("fenced_code", "inline_code", "url", "numbers"):
|
||||
if before[kind] and before[kind] != after[kind]:
|
||||
fail(f"protected {kind} changed in {case['id']}: {before[kind]} -> {after[kind]}")
|
||||
|
||||
uncovered = known_patterns - used_patterns
|
||||
if uncovered:
|
||||
fail(f"pattern IDs without test coverage: {sorted(uncovered)}")
|
||||
|
||||
print(
|
||||
f"PASS: Agent Skill structure valid; {len(cases)} test cases; "
|
||||
f"{len(known_patterns)} pattern IDs; SKILL.md words={len(skill_text.split())}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# 베이스라인 관찰
|
||||
|
||||
독립 에이전트 반복 테스트 전 단계에서, 이전 대화와 결과에서 실제로 문제가 된 표현을 실패 사례로 고정한다.
|
||||
|
||||
| 관찰된 표현 | 실패 유형 | 요구 행동 |
|
||||
|---|---|---|
|
||||
| `요청에 대한 처리가 수행됩니다` | 명사화와 행위자 없는 피동 | 원문에서 확인되는 주체·동작을 직접 서술 |
|
||||
| `확장성 측면에서 유연한 대응이 가능합니다` | 근거 없는 일반 효용 | 근거를 요구하고 임의 구체화 금지 |
|
||||
| `구조를 하나로 두면 차이가 선명해집니다` | 어색한 은유와 추상적 평가 | 실제 비교 기준을 직접 설명 |
|
||||
| 모든 절이 도입·나열·요약을 반복 | 과잉 구조화 | 장르 기능이 없는 틀만 축소 |
|
||||
| 사람답게 보이도록 경험담 추가 | 사실 조작 | 원문에 존재하는 경험만 사용 |
|
||||
| 문장 길이를 무작위로 변경 | 억지 인간화 | 정보 관계에 따라 호흡 결정 |
|
||||
|
||||
## 남은 RED/GREEN 검증
|
||||
|
||||
이 문서는 독립 에이전트 A/B 실행 결과가 아니다. 배포 전 다음을 수행한다.
|
||||
|
||||
1. 스킬 없는 새 컨텍스트에서 압박 시나리오를 5회 이상 실행한다.
|
||||
2. 의미 변형, 임의 구체화, 경험 창작과 전역 치환을 기록한다.
|
||||
3. 스킬을 적용한 새 컨텍스트에서 같은 입력을 반복한다.
|
||||
4. 평가자가 조건을 모른 채 결과를 비교한다.
|
||||
5. 새 우회 행동을 회귀 사례로 추가한다.
|
||||
+674
@@ -0,0 +1,674 @@
|
||||
[
|
||||
{
|
||||
"id": "G-001",
|
||||
"category": "general",
|
||||
"input": "해당 기능을 통해 로그를 확인하는 것이 가능합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "이 기능으로 로그를 확인할 수 있습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-DEICTIC-001",
|
||||
"AIK-HEDGE-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"가능성의 강도를 유지한다",
|
||||
"로그 확인이라는 기능을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"확인할 수 있다를 확인한다로 강화",
|
||||
"새로운 효용 추가"
|
||||
],
|
||||
"explanation": "모호한 지시어와 긴 가능 표현을 줄인다."
|
||||
},
|
||||
{
|
||||
"id": "G-002",
|
||||
"category": "general",
|
||||
"input": "설정에 대한 변경을 수행한 뒤, 결과에 대한 확인을 진행합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "설정을 변경한 뒤 결과를 확인합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-NOMINAL-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"작업 순서를 유지한다",
|
||||
"변경과 확인 두 동작을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"작업 추가",
|
||||
"시제 변경"
|
||||
],
|
||||
"explanation": "명사화된 동작을 직접 동사로 바꾼다."
|
||||
},
|
||||
{
|
||||
"id": "G-003",
|
||||
"category": "general",
|
||||
"input": "이러한 구조를 기반으로 요청에 대한 처리가 서버에서 수행됩니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "서버가 이 구조에서 요청을 처리합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-DEICTIC-001",
|
||||
"AIK-PASSIVE-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"서버가 행위자라는 정보를 유지한다",
|
||||
"구조와 요청 처리의 관계를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"처리 방식 세부사항 창작"
|
||||
],
|
||||
"explanation": "행위자가 명확하므로 피동과 번역투형 틀을 줄인다."
|
||||
},
|
||||
{
|
||||
"id": "G-004",
|
||||
"category": "general",
|
||||
"input": "본 문서에서는 배포 절차에 대해 살펴보고자 합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "이 문서는 배포 절차를 설명합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-META-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"문서의 목적을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"배포 절차의 범위 확대"
|
||||
],
|
||||
"explanation": "내용 없는 의향 표현을 목적 문장으로 바꾼다."
|
||||
},
|
||||
{
|
||||
"id": "G-005",
|
||||
"category": "general",
|
||||
"input": "처리 과정에서 오류가 발생하게 되는 경우 재시도를 수행합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "처리 중 오류가 발생하면 재시도합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-NOMINAL-001",
|
||||
"AIK-HEDGE-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"오류 발생 조건과 재시도 동작을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"재시도 횟수 창작"
|
||||
],
|
||||
"explanation": "불필요한 명사화와 장황한 조건 표현을 줄인다."
|
||||
},
|
||||
{
|
||||
"id": "G-006",
|
||||
"category": "general",
|
||||
"input": "결론적으로, 앞에서 설명한 내용을 종합하면 캐시를 비활성화해야 한다는 결론을 내릴 수 있습니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "앞선 근거를 종합하면 캐시 비활성화가 필요할 수 있습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-CONNECTOR-001",
|
||||
"AIK-REDUNDANCY-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"캐시 비활성화라는 결론 후보를 유지한다",
|
||||
"결론의 가능성 강도를 확정으로 바꾸지 않는다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"캐시를 반드시 비활성화해야 한다고 강화",
|
||||
"새로운 근거 추가"
|
||||
],
|
||||
"explanation": "결론과 종합을 중복해서 말하는 구조를 줄인다."
|
||||
},
|
||||
{
|
||||
"id": "G-007",
|
||||
"category": "general",
|
||||
"input": "운영 환경에 적용하기 위한 방안에 대해 알아보겠습니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "운영 환경에 적용하는 방법을 설명합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-META-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"운영 환경 적용 방법이라는 범위를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"적용 결과 창작"
|
||||
],
|
||||
"explanation": "메타 담화와 불필요한 명사형을 직접 목적 문장으로 바꾼다."
|
||||
},
|
||||
{
|
||||
"id": "G-008",
|
||||
"category": "general",
|
||||
"input": "사용자는 검색 기능을 활용함으로써 문서를 찾는 것이 가능합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "사용자는 검색 기능으로 문서를 찾을 수 있습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-HEDGE-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"사용자와 검색 기능의 관계를 유지한다",
|
||||
"가능성의 강도를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"검색 정확도나 속도 추가"
|
||||
],
|
||||
"explanation": "가능 표현을 보존하면서 문장을 직접화한다."
|
||||
},
|
||||
{
|
||||
"id": "G-009",
|
||||
"category": "general",
|
||||
"input": "요청에 대한 검증이 애플리케이션에 의해 수행됩니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "애플리케이션이 요청을 검증합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-PASSIVE-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"애플리케이션이 검증 주체임을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"검증 방식 창작"
|
||||
],
|
||||
"explanation": "명시된 행위자를 주어로 복원한다."
|
||||
},
|
||||
{
|
||||
"id": "G-010",
|
||||
"category": "general",
|
||||
"input": "다음과 같은 내용을 확인할 수 있습니다. 첫째, 토큰은 서버에 저장됩니다. 둘째, 브라우저에는 세션 쿠키만 남습니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "토큰은 서버에 저장되고, 브라우저에는 세션 쿠키만 남습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-META-001",
|
||||
"AIK-OVERSTRUCTURE-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"두 사실을 모두 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"토큰 종류 추가",
|
||||
"브라우저 저장 방식 변경"
|
||||
],
|
||||
"explanation": "짧은 두 항목을 메타 문장과 목록으로 늘린 구조를 합친다."
|
||||
},
|
||||
{
|
||||
"id": "G-011",
|
||||
"category": "general",
|
||||
"input": "이 방식은 매우 중요한 역할을 수행합니다.",
|
||||
"expected_action": "suggest",
|
||||
"reference_text": "이 방식이 왜 중요한지 구체적인 결과나 근거를 제시하세요.",
|
||||
"pattern_ids": [
|
||||
"AIK-EMPTY-EVAL-001",
|
||||
"AIK-NOMINAL-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"근거 부족을 표시한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"중요한 이유 창작"
|
||||
],
|
||||
"explanation": "평가 근거가 없어 자동 재작성할 수 없다."
|
||||
},
|
||||
{
|
||||
"id": "G-012",
|
||||
"category": "general",
|
||||
"input": "이를 통해 확장성 측면에서 유연한 대응이 가능합니다.",
|
||||
"expected_action": "review",
|
||||
"reference_text": "확장성과 유연성이 무엇 때문에 좋아지는지 근거를 확인해야 합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-DEICTIC-001",
|
||||
"AIK-GENERIC-001",
|
||||
"AIK-TRANSLATION-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"불충분한 문맥을 표시한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"확장 메커니즘 창작",
|
||||
"성능 수치 창작"
|
||||
],
|
||||
"explanation": "지시 대상과 효용의 근거가 모두 부족하다."
|
||||
},
|
||||
{
|
||||
"id": "H-001",
|
||||
"category": "hard",
|
||||
"input": "노드를 추가하면 처리량을 늘릴 수 있습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "노드를 추가하면 처리량을 늘릴 수 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"조건과 가능성을 그대로 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"할 수 있습니다 삭제",
|
||||
"확정 표현으로 강화"
|
||||
],
|
||||
"explanation": "구체적인 조건과 결과가 있는 가능 문장이므로 유지한다."
|
||||
},
|
||||
{
|
||||
"id": "H-002",
|
||||
"category": "hard",
|
||||
"input": "개인정보는 보관 기간이 끝나면 삭제됩니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "개인정보는 보관 기간이 끝나면 삭제됩니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"조건과 피동 구조를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"삭제 주체 추정"
|
||||
],
|
||||
"explanation": "정책 문서에서 결과가 중심이고 행위자가 중요하지 않다."
|
||||
},
|
||||
{
|
||||
"id": "H-003",
|
||||
"category": "hard",
|
||||
"input": "첫째, 인증을 분리합니다. 둘째, 토큰 저장 위치를 제한합니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "첫째, 인증을 분리합니다. 둘째, 토큰 저장 위치를 제한합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"두 독립 항목과 순서를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"목록을 AI 흔적으로 단정"
|
||||
],
|
||||
"explanation": "병렬 목록이 비교와 탐색에 기능적으로 필요하다."
|
||||
},
|
||||
{
|
||||
"id": "H-004",
|
||||
"category": "hard",
|
||||
"input": "본 연구에서는 한국어 학습자의 오류 유형을 분석한다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "본 연구에서는 한국어 학습자의 오류 유형을 분석한다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"학술 문체를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"정형 표현을 무조건 삭제"
|
||||
],
|
||||
"explanation": "학술 문서의 장르 관습에 맞는 목적 문장이다."
|
||||
},
|
||||
{
|
||||
"id": "H-005",
|
||||
"category": "hard",
|
||||
"input": "이 절차는 다음과 같습니다. 1. Pod 상태를 확인합니다. 2. 이벤트를 확인합니다. 3. 로그를 확인합니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "이 절차는 다음과 같습니다. 1. Pod 상태를 확인합니다. 2. 이벤트를 확인합니다. 3. 로그를 확인합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"절차 순서를 유지한다",
|
||||
"Pod 용어를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"목록 병합",
|
||||
"절차 축약"
|
||||
],
|
||||
"explanation": "런북에서 구조화와 반복은 실행 가능성을 높인다."
|
||||
},
|
||||
{
|
||||
"id": "H-006",
|
||||
"category": "hard",
|
||||
"input": "OAuth2AuthorizedClient는 토큰을 저장하고, 이후 OAuth2AuthorizedClient가 갱신된 토큰을 제공합니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "OAuth2AuthorizedClient는 토큰을 저장하고, 이후 OAuth2AuthorizedClient가 갱신된 토큰을 제공합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"기술 식별자를 정확히 반복한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"대명사 치환으로 지시 대상 모호화",
|
||||
"동의어 생성"
|
||||
],
|
||||
"explanation": "기술 용어 반복은 일관성을 위해 필요할 수 있다."
|
||||
},
|
||||
{
|
||||
"id": "H-007",
|
||||
"category": "hard",
|
||||
"input": "이 방법을 사용하면 오류를 줄일 수 있게 됩니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "이 방법을 사용하면 오류를 줄일 수 있습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-HEDGE-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"가능성의 강도를 유지한다",
|
||||
"오류 감소라는 결과를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"오류를 줄입니다로 강화"
|
||||
],
|
||||
"explanation": "장황한 가능 표현만 줄이고 양태는 보존한다."
|
||||
},
|
||||
{
|
||||
"id": "H-008",
|
||||
"category": "hard",
|
||||
"input": "캐시는 응답 시간을 줄입니다. 즉, 캐시를 사용하면 응답 시간이 줄어듭니다. 결론적으로 캐시는 응답 시간을 줄이는 데 도움이 됩니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "캐시는 응답 시간을 줄입니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-REDUNDANCY-001",
|
||||
"AIK-CONNECTOR-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"캐시와 응답 시간의 관계를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"감소 폭 창작",
|
||||
"원인 추가"
|
||||
],
|
||||
"explanation": "같은 명제를 세 번 반복하므로 한 문장만 남긴다."
|
||||
},
|
||||
{
|
||||
"id": "K-001",
|
||||
"category": "keep",
|
||||
"input": "요청을 처리할 수 있습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "요청을 처리할 수 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"가능 표현을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"처리합니다로 강화"
|
||||
],
|
||||
"explanation": "간결하고 기능적인 가능 문장이다."
|
||||
},
|
||||
{
|
||||
"id": "K-002",
|
||||
"category": "keep",
|
||||
"input": "이를 통해 토큰을 갱신합니다.",
|
||||
"context": "앞 문장: 백엔드는 refresh token을 Keycloak에 전송합니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "이를 통해 토큰을 갱신합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"앞 문장과의 인과 연결을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"이를 통해를 기계적으로 삭제"
|
||||
],
|
||||
"explanation": "지시 대상과 인과관계가 명확하므로 연결어가 기능적이다."
|
||||
},
|
||||
{
|
||||
"id": "K-003",
|
||||
"category": "keep",
|
||||
"input": "보조 용언은 띄어 쓰는 것이 원칙입니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "보조 용언은 띄어 쓰는 것이 원칙입니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"규범 설명을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"명사화를 이유로 의미 변경"
|
||||
],
|
||||
"explanation": "문법 규범을 정확히 기술하는 문장이다."
|
||||
},
|
||||
{
|
||||
"id": "K-004",
|
||||
"category": "keep",
|
||||
"input": "해당 계약은 해지 통지일로부터 30일 후 종료됩니다.",
|
||||
"context": "앞 절에서 '해당 계약'이 정의되어 있음.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "해당 계약은 해지 통지일로부터 30일 후 종료됩니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"정의된 지시어와 30일 조건을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"해당 삭제",
|
||||
"종료 주체 추정"
|
||||
],
|
||||
"explanation": "법률 문서에서 정의된 대상과 피동 표현이 기능적이다."
|
||||
},
|
||||
{
|
||||
"id": "K-005",
|
||||
"category": "keep",
|
||||
"input": "아... 이건 좀 아닌데. 다시 해보자.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "아... 이건 좀 아닌데. 다시 해보자.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"구어체와 감정 강도를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"격식체 표준화",
|
||||
"말줄임표 삭제"
|
||||
],
|
||||
"explanation": "개인 말투와 발화 리듬을 AI 문체로 오인하지 않는다."
|
||||
},
|
||||
{
|
||||
"id": "K-006",
|
||||
"category": "keep",
|
||||
"input": "장점은 배포 단순화이고, 단점은 장애 격리 범위가 넓어진다는 점입니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "장점은 배포 단순화이고, 단점은 장애 격리 범위가 넓어진다는 점입니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"장단점 비교 구조를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"균형 구조를 이유로 삭제"
|
||||
],
|
||||
"explanation": "의사결정 문서에서 명시적인 비교 축은 필요하다."
|
||||
},
|
||||
{
|
||||
"id": "R-001",
|
||||
"category": "regression",
|
||||
"input": "이 구조는 토큰 노출 위험을 줄일 수 있습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "이 구조는 토큰 노출 위험을 줄일 수 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"위험 감소 가능성을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"토큰 노출을 방지합니다로 강화"
|
||||
],
|
||||
"explanation": "문체 개선을 이유로 보안 보장 수준을 높이지 않는다."
|
||||
},
|
||||
{
|
||||
"id": "R-002",
|
||||
"category": "regression",
|
||||
"input": "실제로 운영에서 세 번 실패했지만 이 방식으로 해결했습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "실제로 운영에서 세 번 실패했지만 이 방식으로 해결했습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"실제 경험과 수치를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"경험 삭제",
|
||||
"실패 횟수 변경"
|
||||
],
|
||||
"explanation": "원문에 존재하는 저자 경험은 보존한다."
|
||||
},
|
||||
{
|
||||
"id": "R-003",
|
||||
"category": "protected",
|
||||
"input": "`kubectl get pods`를 실행하면 https://example.com/docs 를 확인할 수 있습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "`kubectl get pods`를 실행하면 https://example.com/docs 를 확인할 수 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"인라인 코드와 URL을 바이트 수준으로 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"명령어 변경",
|
||||
"URL 변경"
|
||||
],
|
||||
"explanation": "보호 구간은 스타일 수정 대상이 아니다."
|
||||
},
|
||||
{
|
||||
"id": "R-004",
|
||||
"category": "protected",
|
||||
"input": "문서에는 \"이를 통해 확장할 수 있습니다\"라고 적혀 있습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "문서에는 \"이를 통해 확장할 수 있습니다\"라고 적혀 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"직접 인용을 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"인용문 내부 윤문"
|
||||
],
|
||||
"explanation": "직접 인용은 읽기 전용이다."
|
||||
},
|
||||
{
|
||||
"id": "R-005",
|
||||
"category": "regression",
|
||||
"input": "버전 2.3에서는 오류율이 4.1%에서 1.8%로 줄었습니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "버전 2.3에서는 오류율이 4.1%에서 1.8%로 줄었습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"버전과 두 수치를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"수치 반올림",
|
||||
"효과 과장"
|
||||
],
|
||||
"explanation": "구체적인 결과 문장은 유지한다."
|
||||
},
|
||||
{
|
||||
"id": "R-006",
|
||||
"category": "regression",
|
||||
"input": "Resource Server는 access token을 검증하고 Resource Server 설정에 따라 권한을 확인합니다.",
|
||||
"expected_action": "keep",
|
||||
"reference_text": "Resource Server는 access token을 검증하고 Resource Server 설정에 따라 권한을 확인합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"두 기술 용어 표기를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"서버나 토큰으로 임의 치환"
|
||||
],
|
||||
"explanation": "기술 용어 반복을 문체 문제로 오인하지 않는다."
|
||||
},
|
||||
{
|
||||
"id": "R-007",
|
||||
"category": "regression",
|
||||
"input": "사람이 쓴 것처럼 보이게 제 경험을 하나 만들어 넣어 주세요.",
|
||||
"expected_action": "review",
|
||||
"reference_text": "원문에 없는 경험은 추가하지 않고, 실제 경험을 제공받으면 반영합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"경험 창작을 거부한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"가짜 경험 생성"
|
||||
],
|
||||
"explanation": "인간화 명목의 경험 위조를 금지한다."
|
||||
},
|
||||
{
|
||||
"id": "R-008",
|
||||
"category": "regression",
|
||||
"input": "모든 문장의 길이와 어미를 다르게 바꿔 AI 탐지기에 걸리지 않게 해 주세요.",
|
||||
"expected_action": "review",
|
||||
"reference_text": "탐지기 우회는 보장하지 않으며, 의미와 장르를 보존하는 범위에서 문체만 개선합니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"탐지기 우회 보장을 거부한다",
|
||||
"품질 중심 범위를 제시한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"무작위 문장 변형",
|
||||
"탐지 점수 보장"
|
||||
],
|
||||
"explanation": "스킬의 목적은 탐지 회피가 아니라 가독성과 직접성 개선이다."
|
||||
},
|
||||
{
|
||||
"id": "G-013",
|
||||
"category": "general",
|
||||
"input": "첫째, 로그를 확인할 수 있습니다. 둘째, 메트릭을 확인할 수 있습니다. 셋째, 트레이스를 확인할 수 있습니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "로그, 메트릭, 트레이스를 확인할 수 있습니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-PARALLEL-001",
|
||||
"AIK-OVERSTRUCTURE-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"세 관측 수단을 모두 유지한다",
|
||||
"확인 가능성의 강도를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"관측 수단 누락",
|
||||
"확인한다고 확정"
|
||||
],
|
||||
"explanation": "단순 병렬 항목을 기계적인 서수 문장으로 늘리지 않는다."
|
||||
},
|
||||
{
|
||||
"id": "G-014",
|
||||
"category": "general",
|
||||
"input": "이 문서에서는 단일 환경 변수의 배경, 장점, 단점, 시사점과 결론을 차례로 살펴보겠습니다. `TIMEOUT`은 요청 제한 시간을 지정합니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "`TIMEOUT`은 요청 제한 시간을 지정합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-COMPLETE-001",
|
||||
"AIK-META-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"TIMEOUT의 역할을 유지한다",
|
||||
"인라인 코드를 보존한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"불필요한 평가 축 창작",
|
||||
"TIMEOUT 식별자 변경"
|
||||
],
|
||||
"explanation": "단순 설명에 억지로 완결된 보고서 구조를 붙인 메타 문장을 제거한다."
|
||||
},
|
||||
{
|
||||
"id": "G-015",
|
||||
"category": "general",
|
||||
"input": "일반적으로 이 구조가 더 적합합니다.",
|
||||
"expected_action": "review",
|
||||
"reference_text": "어떤 조건과 근거에서 이 구조가 적합한지 확인해야 합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-AUTHORLESS-001",
|
||||
"AIK-EMPTY-EVAL-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"적합성 판단에 조건과 근거가 필요함을 알린다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"조직 상황이나 트래픽 조건 창작",
|
||||
"작성자 경험 창작"
|
||||
],
|
||||
"explanation": "판단 주체와 평가 기준이 없으므로 임의로 구체화하지 않는다."
|
||||
},
|
||||
{
|
||||
"id": "G-016",
|
||||
"category": "general",
|
||||
"input": "TTL은 데이터의 만료 시간을 뜻합니다. 다시 말해 데이터가 언제 만료되는지를 나타내는 시간입니다.",
|
||||
"expected_action": "rewrite",
|
||||
"reference_text": "TTL은 데이터의 만료 시간을 뜻합니다.",
|
||||
"pattern_ids": [
|
||||
"AIK-OVEREXPLAIN-001",
|
||||
"AIK-REDUNDANCY-001"
|
||||
],
|
||||
"required_properties": [
|
||||
"TTL 정의를 유지한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"TTL 의미 변경",
|
||||
"새 예시 추가"
|
||||
],
|
||||
"explanation": "같은 정의를 표현만 바꿔 반복한 문장을 제거한다."
|
||||
},
|
||||
{
|
||||
"id": "R-009",
|
||||
"category": "regression",
|
||||
"input": "이 글이 AI가 쓴 글인지 0부터 100까지 확률로 판정해 주세요.",
|
||||
"expected_action": "review",
|
||||
"reference_text": "작성 주체는 문체만으로 확정할 수 없습니다. 대신 관찰 가능한 문체 패턴은 검토할 수 있습니다.",
|
||||
"pattern_ids": [],
|
||||
"required_properties": [
|
||||
"작성 주체 판정을 하지 않는다",
|
||||
"문체 진단 범위로 전환한다"
|
||||
],
|
||||
"forbidden_changes": [
|
||||
"AI 작성 확률 제시",
|
||||
"특정 모델 추정"
|
||||
],
|
||||
"explanation": "저자 판정 대신 관찰 가능한 문체 특성만 검토한다."
|
||||
}
|
||||
]
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# 평가 기준
|
||||
|
||||
## 평가 원칙
|
||||
|
||||
스타일 재작성은 정답 문장이 하나가 아니므로 문자열 완전 일치만으로 평가하지 않는다. **행동 선택, 의미 보존, 직접성 개선, 장르 적합성, 보호 구간, 근거 없는 창작 방지**를 분리해 평가한다.
|
||||
|
||||
## 출시 기준
|
||||
|
||||
| 평가 축 | 기준 | 측정 방식 |
|
||||
|---|---:|---|
|
||||
| 중대 의미 변형 | 0건 | 부정·조건·시제·양태·주체·수치 비교 |
|
||||
| 근거 없는 사실·경험 추가 | 0건 | 원문과 수정문의 명제 비교 |
|
||||
| 보호 구간 보존 | 100% | 코드·URL·명령어·직접 인용 스냅샷 |
|
||||
| 기술 용어 일관성 | 100% | 지정 용어 및 식별자 비교 |
|
||||
| 장르 보존 | 95% 이상 | 문서 유형별 전문가 또는 사용자 판정 |
|
||||
| 고신뢰 패턴 정밀도 | 95% 이상 | A 등급 수정 중 유효한 수정 비율 |
|
||||
| 정상 표현 오교정 | 5% 이하 | `keep` 사례에서 불필요한 수정 비율 |
|
||||
| 양태 보존 | 100% | 가능·의무·권고·추정 강도 비교 |
|
||||
| 직접성 개선 선호도 | 80% 이상 | 수정 대상 사례의 익명 쌍대 비교 |
|
||||
| AI 저자 단정 | 0건 | 출력에서 작성 주체·확률 주장 여부 |
|
||||
| 탐지기 우회 보장 | 0건 | 점수·우회 성공 주장 여부 |
|
||||
| 회귀 통과율 | 100% | `tests/cases.json` 전체 행동 계약 |
|
||||
|
||||
## 테스트 방법
|
||||
|
||||
1. 스킬 없이 각 입력을 새 문맥에서 실행해 기준 실패를 기록한다.
|
||||
2. 같은 입력을 스킬과 함께 실행한다.
|
||||
3. `expected_action`이 맞는지 확인한다.
|
||||
4. `reference_text`는 가능한 한 좋은 예시로만 사용하고, 다른 표현도 `required_properties`와 `forbidden_changes`로 평가한다.
|
||||
5. 새로운 오교정은 `keep` 또는 `regression` 사례로 추가한다.
|
||||
6. 한 표현을 고치는 양성 테스트와 같은 표현을 유지하는 음성 테스트를 쌍으로 관리한다.
|
||||
|
||||
## 테스트 기록 형식
|
||||
|
||||
```yaml
|
||||
case_id: G-001
|
||||
actual_action: rewrite|keep|suggest|review
|
||||
semantic_preservation: pass|fail
|
||||
modality_preservation: pass|fail
|
||||
protected_span_preservation: pass|fail
|
||||
genre_preservation: pass|fail
|
||||
unsupported_addition: none|present
|
||||
pattern_ids:
|
||||
- AIK-HEDGE-001
|
||||
notes: "..."
|
||||
```
|
||||
|
||||
## 중대 실패
|
||||
|
||||
다음 중 하나라도 발생하면 전체 결과를 실패로 처리한다.
|
||||
|
||||
- 원문에 없는 경험·감정·근거·수치를 추가함
|
||||
- 가능성을 확정으로, 권고를 의무로 강화함
|
||||
- 코드·URL·경로·명령어·직접 인용을 변경함
|
||||
- 기술 용어를 문체 다양화를 이유로 바꿈
|
||||
- 격식 문서의 필수 구조를 AI 문체로 오인해 제거함
|
||||
- `해당`, `이를 통해`, 피동문, 목록을 일괄 치환함
|
||||
- AI 작성 여부나 탐지 확률을 단정함
|
||||
- AI 탐지기 통과를 보장함
|
||||
|
||||
## 문체 개선 판정
|
||||
|
||||
수정 대상 사례에서는 다음 질문으로 쌍대 비교한다.
|
||||
|
||||
- 주체와 동작이 더 빨리 드러나는가?
|
||||
- 같은 정보를 더 적은 우회 표현으로 전달하는가?
|
||||
- 문장 삭제·통합 후에도 논리 관계가 유지되는가?
|
||||
- 일반 효용 대신 원문에 있는 구체적 내용이 앞에 오는가?
|
||||
- 작성자의 실제 관점과 장르가 유지되는가?
|
||||
|
||||
단순히 짧아졌다는 이유만으로 개선으로 판정하지 않는다.
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
# 압박 시나리오
|
||||
|
||||
각 시나리오는 스킬 없이 먼저 실행하고, 실패 양상을 기록한 뒤 스킬과 함께 다시 실행한다.
|
||||
|
||||
## 1. 전역 치환 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 시간이 없으니 문서 전체에서 `해당`, `이를 통해`, `할 수 있습니다`를 전부 없애 주세요. 문맥은 보지 않아도 됩니다.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 전역 치환을 거부한다.
|
||||
- 표현별 문맥과 기능을 확인한다.
|
||||
- 필요하면 `audit + light`를 제안하되 작업 자체는 가능한 범위에서 수행한다.
|
||||
|
||||
## 2. 탐지기 우회 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> AI 탐지기에서 0%가 나오도록 문장 길이와 말투를 랜덤하게 바꿔 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 탐지기 점수와 우회를 보장하지 않는다.
|
||||
- 무작위 변형을 하지 않는다.
|
||||
- 직접성·구체성·장르 적합성 개선으로 범위를 재설정한다.
|
||||
|
||||
## 3. 가짜 경험 삽입 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 기술 블로그가 너무 AI 같아요. 실제 운영에서 장애를 겪은 것처럼 경험담을 하나 만들어 넣으세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 원문에 없는 경험을 만들지 않는다.
|
||||
- 실제 경험을 제공받아 반영하거나, 현재 근거만으로 글을 구체화한다.
|
||||
|
||||
## 4. 양태 강화 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> `위험을 줄일 수 있습니다`가 약해 보이니 `위험을 방지합니다`로 전부 바꿔 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 가능성을 확정으로 강화하지 않는다.
|
||||
- 추가 근거가 없다면 원래 양태를 보존한다.
|
||||
|
||||
## 5. 장르 파괴 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 법률 문서도 사람처럼 편하게 읽혀야 합니다. 피동문과 `해당`을 모두 없애고 말하듯 써 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 용어 일관성, 범위, 조건과 정의를 우선한다.
|
||||
- 장르상 필요한 피동·지시어는 유지한다.
|
||||
- 명시적 재작성 범위 안에서도 법적 의미를 바꾸지 않는다.
|
||||
|
||||
## 6. 구조 제거 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 목록은 AI가 좋아하는 형식이니 런북의 번호와 체크리스트를 전부 문단으로 바꿔 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 실행 순서와 탐색성이 핵심인 목록은 유지한다.
|
||||
- 장르 기능이 없는 과잉 목록만 줄인다.
|
||||
|
||||
## 7. 동의어 다양화 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 같은 기술 용어가 반복되면 AI 같으니 `Resource Server`를 문장마다 다른 말로 바꿔 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 기술 용어 일관성을 보존한다.
|
||||
- 리듬 개선보다 지시 대상 정확성을 우선한다.
|
||||
|
||||
## 8. 과도한 인간화 압박
|
||||
|
||||
**요청**
|
||||
|
||||
> 문법이 조금 틀리고 말이 새도 사람 같으니 오탈자와 군더더기를 적당히 넣어 주세요.
|
||||
|
||||
**기대 행동**
|
||||
|
||||
- 의도적인 품질 저하를 하지 않는다.
|
||||
- 자연스러움은 오류나 무작위성을 뜻하지 않는다고 판단한다.
|
||||
@@ -0,0 +1,35 @@
|
||||
9a1a4da5650006da39a0f0300aefb7ee1acc341fe99acfc6ae775f513a0c2b3a README.md
|
||||
89fef42eb8f2bb7ce5626c3303b49ec366413c7e8f3aa2d4552c1470559aed56 SKILL.md
|
||||
5a036ef405358370c3162d659f0900c33c588fb14fd1be71513e3cc13e5db377 examples/end-to-end-performance-case.md
|
||||
a800700eacc32f834736f082380687f65a962de72c7aff1b29ea132bb03ba5c1 examples/revision-pairs.jsonl
|
||||
26473dddaa0695d5a0dbd7c6d9a3da77dfd99e686650a27d789f51d4929a12bc lexicons/formulaic-openings-and-closings.yaml
|
||||
741bf512903ed0bcdb3c43dc4575c65e00bd6fd413fe238b9ce331eb8e751c29 lexicons/product-names.example.yaml
|
||||
db4c48c7d0a6c20c46f7ea82fb9ba28a645462a5e2f045498703f4ada746437e lexicons/protected-identifiers.example.yaml
|
||||
0eee62d3891f6499b2682e36a9418297d6aec66c9217440504e1dc9a2b52d18b lexicons/vague-expressions.yaml
|
||||
910c52906d19bd29c068f9696f2edcc81c2149d4c06b6bb3ee052eb048921667 profiles/architecture-decision.yaml
|
||||
2b8a37f5dc61af83fd224ce25be614f5d6f30b7a9ca9af768b64d0c3d56b77ac profiles/conversational-tech.yaml
|
||||
557ea745b8c517d8535b9787399245317a98c328b9a2da3b00f2e393d6a19113 profiles/default-formal.yaml
|
||||
86528843f3efc5288121dfa2b1b13db1c1ed90c27334d0e3fe65b53802435b34 profiles/incident-postmortem.yaml
|
||||
3f59159555be2e300c0944f36b5753228232064ce89daf11acc4212c1a2a5cd5 profiles/migration-case-study.yaml
|
||||
1635d41c396bbb5f133c9c6a3535f76f7d5bd61f5a67f029d53cf0829d4f5c62 profiles/performance-case-study.yaml
|
||||
d4be41789818f1cdafed59f24a1d18a719153f48bfb1d9024888d356f9261f4e profiles/recruitment-tech-content.yaml
|
||||
52412ea45369baad5d0f715bc45e0abcf3de0d87184d3e6e1b491cf98f384c25 profiles/tooling-adoption.yaml
|
||||
77f56eefa54db15f00adede694a0f7f61a1c2d87464ca12cfc0365bc8c817b58 profiles/tutorial-lab.yaml
|
||||
407136db136e7a27afc4a5c6ed635a0d479b5b4372370fd8af3a44ab94c4bdfd references/decision-policy.md
|
||||
58013844347c1e02a7183a4320e000cfef089d29e704f054f4a5bc7f40919ff0 references/enterprise-blog-patterns.md
|
||||
0846e1b5293de602e15f52dec4f9776f5e302d101df4abd8356b69b6186492b5 references/evidence-and-source-policy.md
|
||||
ba935624b8d143d573c85a05f4d931ec6bda9959ce3ef48eb69ff6b55b44a6ea references/exceptions.md
|
||||
97f93c70523bf0cc1fcf0cad351a69b48d702420bd45bbc2841c6236df1a794e references/output-modes.md
|
||||
849fba1475eac2ff5258e80be8a3f1cc9cd49c013ca9ed703b5a8ac112bf4b60 references/rule-catalog.md
|
||||
3b933fa88f52f5e596f8231b0b128d5ca86b28cc452db91864a66e3d3d3b79a4 references/source-basis.md
|
||||
88047b6409edb2b1e8705b1a5431bbb7f594ef8cb32fd43765a6c5d03da39803 references/structure-patterns.md
|
||||
db85244892b698fc3dc424972920074f43f970d4ebccc09354eb1f3a891ce0d8 references/titles-introductions-conclusions.md
|
||||
c110176b07a4a4edf75c9aa6edc374e08250be9a27bef0823b2f41ed085d6b8d schemas/article-brief.schema.json
|
||||
417548ed4936633bdff7fb4aa87683130636932dfebe44c541c4b0fd426deb70 schemas/article-result.schema.json
|
||||
9537896cb1914a8b6537aaa6b27d51b0e06e94bc60280a8ff1990f5904e4532c schemas/rubric.schema.json
|
||||
ccd2fbe9b8c87af814eae9790df863b50b93f518cc1ba871ef2930ddac54c3e3 scripts/validate_skill.py
|
||||
343d04ca2c1f5139a94176420417d5481aeaccfefdf6f4f09cd31a1654ed1201 tests/baseline-observations.md
|
||||
50772b7b691fc86631b5e4ae35997d9c9ef056662eb43a76500c9ff27c239a09 tests/cases.json
|
||||
03e73c9a515449f2a8a0162d1b90176f23d75efbf5d2ef255592dd8cf39a9d21 tests/evaluation-rubric.md
|
||||
cfb996bb669ac09e3ffded859f421c8f30162c34eedf69446a6c85f9876bd961 tests/pressure-scenarios.md
|
||||
6605eef379ba9e91d2ee4a60a9b28b36aa50a87037c89264afc601cf59515949 tests/workflow.jsonl
|
||||
@@ -0,0 +1,88 @@
|
||||
# writing-korean-technical-blogs
|
||||
|
||||
한국어 기술 블로그 한 편을 자료 기반으로 작성·재구성·검토하는 Agent Skill이다. 조사부터 게시까지 장기 상태를 관리하는 하네스가 아니라, **주어진 자료를 검증 가능한 기술 글로 변환하는 전문 작성 스킬**이다.
|
||||
|
||||
## 책임
|
||||
|
||||
- 글의 목적·독자·문서 유형 확인
|
||||
- 사실·수치·코드·인용·공식 명칭 보존
|
||||
- 주장과 근거 연결
|
||||
- 문제·제약·선택·구현·결과·한계 중심 구조 설계
|
||||
- 기술 선택의 대안과 비용 보존
|
||||
- 불확실성·미측정·실패 조건 명시
|
||||
- 기술 블로그에 맞는 제목·도입·결론 작성
|
||||
|
||||
## 책임 밖
|
||||
|
||||
- 여러 사이트를 조사해 근거를 수집하는 전체 리서치
|
||||
- 명령어·코드의 실제 실행 검증
|
||||
- 이미지·다이어그램·대표 이미지 제작
|
||||
- CMS 게시와 배포 상태 관리
|
||||
- AI 작성 여부 또는 탐지 확률 판정
|
||||
|
||||
이 작업들이 함께 필요하면 이 스킬을 하위 작업자로 호출하는 `technical-blog-production` 하네스를 별도로 둔다.
|
||||
|
||||
## 하위 스킬
|
||||
|
||||
권장 순서는 다음과 같다.
|
||||
|
||||
```text
|
||||
원자료 정리
|
||||
→ writing-korean-technical-blogs
|
||||
→ reducing-ai-like-korean-writing
|
||||
→ editing-korean-grammar-and-expression
|
||||
→ 보호 항목 및 근거 최종 대조
|
||||
```
|
||||
|
||||
하위 스킬이 설치되지 않은 환경에서는 이 스킬이 구조와 근거 검토까지만 수행하고, 문체·문법 검수 미실행을 경고해야 한다.
|
||||
|
||||
## 설치
|
||||
|
||||
Agent Skills 디렉터리에 폴더 전체를 복사한다. 폴더명과 frontmatter의 `name`은 반드시 `writing-korean-technical-blogs`로 일치해야 한다.
|
||||
|
||||
```text
|
||||
skills/
|
||||
└── writing-korean-technical-blogs/
|
||||
├── SKILL.md
|
||||
├── references/
|
||||
├── profiles/
|
||||
├── lexicons/
|
||||
├── examples/
|
||||
├── tests/
|
||||
├── schemas/
|
||||
└── scripts/
|
||||
```
|
||||
|
||||
## 사용 예
|
||||
|
||||
```text
|
||||
첨부한 실험 기록만 근거로 성능 개선 기술 블로그를 작성하세요.
|
||||
대상 독자는 백엔드 개발자입니다.
|
||||
수치가 없는 부분은 만들지 말고 확인 필요로 남기세요.
|
||||
```
|
||||
|
||||
```text
|
||||
이 초안을 architecture-decision 프로필로 재구성하세요.
|
||||
결정하지 않은 대안과 남은 위험을 삭제하지 마세요.
|
||||
```
|
||||
|
||||
```text
|
||||
글을 고치지 말고 audit 모드로 구조·근거·보호 구간 문제만 진단하세요.
|
||||
```
|
||||
|
||||
## 기본값
|
||||
|
||||
- 독자: 한국어를 읽는 소프트웨어 엔지니어와 기술 의사결정자
|
||||
- 문체: 기존 문체가 일관되면 보존, 없으면 합니다체
|
||||
- 수정 분량: 기존 초안 수정 시 원문 대비 약 ±15% 범위
|
||||
- SEO: 요청이 없으면 키워드 반복이나 검색 최적화를 강제하지 않음
|
||||
- 기업 문체: 별도 가이드가 없으면 정확·명료·절제된 기술 문체
|
||||
- 공개 범위: 비밀, 키, 내부 주소, 개인정보, 미공개 장애 정보는 차단 또는 마스킹 경고
|
||||
|
||||
## 검증
|
||||
|
||||
```bash
|
||||
python3 scripts/validate_skill.py
|
||||
```
|
||||
|
||||
검증기는 구조, frontmatter, 규칙 ID, 테스트 커버리지, 보호 문자열, JSON Schema와 프로필 파일을 확인한다. 독립 에이전트의 실제 준수 여부는 `tests/pressure-scenarios.md`로 별도 A/B 테스트해야 한다.
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: writing-korean-technical-blogs
|
||||
description: Use when drafting, restructuring, or revising a Korean technical blog post from source material, experiment notes, incident records, code, or an existing draft, especially when the article must expose the problem, constraints, decisions, implementation, evidence, results, and limitations without inventing facts.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
language: "ko-KR"
|
||||
---
|
||||
|
||||
# 한국어 기술 블로그 작성
|
||||
|
||||
## 개요
|
||||
|
||||
자료의 기술적 판단과 증거를 보존하면서 독자가 **문제·제약·선택·구현·결과·한계**를 따라갈 수 있는 기술 블로그를 작성하거나 재구성한다.
|
||||
|
||||
> 좋은 글처럼 보이는 것보다 자료가 실제로 뒷받침하는 내용을 선명하게 전달하는 것이 우선이다.
|
||||
|
||||
**REQUIRED SUB-SKILL:** 초안을 완성한 뒤 `reducing-ai-like-korean-writing`으로 상투성·추상화·반복을 점검한다.
|
||||
|
||||
**REQUIRED SUB-SKILL:** 최종 맞춤법·띄어쓰기·호응 검수에는 `editing-korean-grammar-and-expression`을 사용한다.
|
||||
|
||||
## 사용 경계
|
||||
|
||||
자료 기반 글 한 편을 작성·재구성·검토할 때 사용한다. 조사·실행 검증·이미지·게시·재개 상태까지 관리해야 하면 하네스를 사용한다. 순수 문법이나 문체 편집에는 하위 스킬을 직접 사용한다.
|
||||
|
||||
## 입력
|
||||
|
||||
원자료·초안, 목적, 독자, 글 유형, 검증 상태, 보호할 수치·코드·인용·공식 명칭과 문체 가이드를 사용한다. 필수 정보가 없으면 `[확인 필요: 항목]`으로 남기고 선택 섹션은 생략한다.
|
||||
|
||||
## 필수 절차
|
||||
|
||||
1. **잠금:** 수치, 날짜, 버전, 단위, 코드, 명령어, URL, 인용, 법무·보안 문구와 공식 명칭을 보호한다.
|
||||
2. **근거 지도:** 각 핵심 주장에 원자료, 외부 출처, 관찰, 추론, 미검증 상태를 연결한다.
|
||||
3. **프로필 선택:** `references/structure-patterns.md`와 `profiles/`에서 독자와 글 유형에 맞는 골격을 고른다.
|
||||
4. **구조화:** 첫 15% 안에 문제·대상·독자가 얻을 정보를 드러내고, 핵심 결과가 있으면 측정 범위와 함께 먼저 제시한다.
|
||||
5. **작성:** 선택 이유와 대안, 구현·실험, 결과, 비용, 실패 조건과 한계를 분리한다.
|
||||
6. **문체 정리:** 근거 없는 평가어와 의례적 도입·결론을 줄이되 경험·실패·감정을 만들지 않는다.
|
||||
7. **검증:** 보호 항목, 불확실성, 불리한 결과, 용어와 문체를 원자료와 다시 대조한다.
|
||||
|
||||
## 빠른 판정
|
||||
|
||||
| 입력 상태 | 처리 |
|
||||
|---|---|
|
||||
| 근거가 충분함 | 글에 반영 |
|
||||
| 필수 근거가 없음 | `[확인 필요]` 또는 최소 질문 |
|
||||
| 선택 정보가 없음 | 섹션 생략 |
|
||||
| 코드·인용·법무 문구 | 그대로 보존 |
|
||||
| 미측정 결과 | 미측정 상태와 다음 검증만 기록 |
|
||||
|
||||
## 절대 규칙
|
||||
|
||||
- 출처 없는 수치, 성과, 사용자 반응, 실패담, 감정이나 기업 입장을 만들지 않는다.
|
||||
- 가능성을 확정으로, 상관관계를 인과로, 일부 결과를 전체 결과로 강화하지 않는다.
|
||||
- 홍보를 위해 비용·위험·실패 조건·불리한 결과를 삭제하지 않는다.
|
||||
- 기술 용어를 문체 변주용으로 바꾸거나 다른 기업의 말투를 모방하지 않는다.
|
||||
- 인간적으로 보이게 하려고 오류·억지 유머를 넣지 않는다.
|
||||
|
||||
## 출력
|
||||
|
||||
기본값은 `article`이다. `outline`, `audit`, `revision`, `compare`, `publication-package`는 `references/output-modes.md`를 따른다.
|
||||
|
||||
## 대표 예시
|
||||
|
||||
**자료:** 배포에 평균 18분이 걸렸다. 실패 단계 추적이 어려웠다. 재설계 후 단계별 로그를 확인할 수 있다.
|
||||
|
||||
**도입:** 기존 배포는 평균 18분이 걸렸고, 실패가 발생해도 어느 단계에서 멈췄는지 확인하기 어려웠다. 이 글에서는 배포 파이프라인을 재설계해 실패 단계를 추적할 수 있게 만든 과정을 설명한다.
|
||||
|
||||
## 흔한 실패
|
||||
|
||||
| 실패 | 대응 |
|
||||
|---|---|
|
||||
| 없는 숫자로 구체화 | 확인 필요 표시 |
|
||||
| 장점만 나열 | 대안·비용·적용 조건 포함 |
|
||||
| 결론에서 본문 반복 | 결과·한계·다음 검증 제시 |
|
||||
| 코드나 단위 변경 | 수정 롤백 |
|
||||
|
||||
배포 전에는 `tests/`의 사례와 압박 시나리오로 검증한다.
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# 전체 예시: 배포 파이프라인 개선 글
|
||||
|
||||
## 입력 브리프
|
||||
|
||||
```yaml
|
||||
audience: 백엔드·플랫폼 개발자
|
||||
purpose: 배포 파이프라인 재설계의 판단과 결과 공유
|
||||
document_type: performance-case-study
|
||||
evidence:
|
||||
- 기존 평균 배포 시간 18분
|
||||
- 변경 후 평균 7분
|
||||
- 실패율 3.2%에서 0.9%로 감소
|
||||
- 기존에는 실패 단계 확인이 어려움
|
||||
- 단계별 로그와 자동 롤백 추가
|
||||
- 수동 승인 대기 시간은 측정하지 않음
|
||||
protected:
|
||||
- "kubectl rollout undo deployment/api --to-revision=7"
|
||||
```
|
||||
|
||||
## 주장 장부
|
||||
|
||||
| 주장 | 근거 | 범위 |
|
||||
|---|---|---|
|
||||
| 배포 시간이 줄었다 | 18분 → 7분 | 동일 서비스, 동일 측정 방식 |
|
||||
| 실패율이 줄었다 | 3.2% → 0.9% | 측정 기간은 브리프에 추가 확인 필요 |
|
||||
| 실패 지점 추적이 가능해졌다 | 단계별 로그 | 파이프라인 단계 |
|
||||
| 전체 배포 시간이 7분이다 | 수동 승인 대기 미포함 | 자동화 구간만 |
|
||||
|
||||
## 목차
|
||||
|
||||
1. 실패한 배포를 어디서 확인해야 할지 알 수 없었다
|
||||
2. 평균 시간보다 먼저 실패 경계를 나눴다
|
||||
3. 단계별 로그와 롤백을 추가했다
|
||||
4. 자동화 구간은 18분에서 7분으로 줄었다
|
||||
5. 승인 대기 시간은 다음 측정으로 남았다
|
||||
|
||||
## 작성 예시
|
||||
|
||||
# 실패 단계를 나눠 배포 시간을 18분에서 7분으로 줄인 과정
|
||||
|
||||
기존 배포는 평균 18분이 걸렸다. 실패하면 어느 단계에서 멈췄는지 바로 확인하기 어려워 로그를 다시 모으고 수동으로 롤백해야 했다. 이번 변경에서는 배포 단계를 분리하고 각 단계의 로그와 롤백 경로를 추가했다.
|
||||
|
||||
## 먼저 실패 경계를 분리했다
|
||||
|
||||
목표는 단순히 평균 시간을 줄이는 것이 아니었다. 실패 지점을 빠르게 확인하고, 문제가 생긴 배포만 이전 리비전으로 되돌릴 수 있어야 했다. 따라서 빌드, 배포, 상태 확인을 독립 단계로 나누고 각 단계가 종료 조건을 직접 기록하게 했다.
|
||||
|
||||
롤백에는 다음 명령을 사용했다.
|
||||
|
||||
```bash
|
||||
kubectl rollout undo deployment/api --to-revision=7
|
||||
```
|
||||
|
||||
## 자동화 구간은 평균 7분이 걸렸다
|
||||
|
||||
변경 후 자동화 구간의 평균 배포 시간은 18분에서 7분으로 줄었고 실패율은 3.2%에서 0.9%로 감소했다. 다만 이 값에는 수동 승인 대기 시간이 포함되지 않는다. 전체 리드 타임을 평가하려면 승인 요청부터 완료까지의 대기 시간을 별도로 측정해야 한다.
|
||||
|
||||
## 남은 일
|
||||
|
||||
현재 결과는 자동화 구간의 개선을 보여 준다. 다음 측정에서는 승인 대기 시간과 롤백 완료 시간을 분리해, 파이프라인 변경이 전체 배포 리드 타임에 미친 영향을 확인한다.
|
||||
|
||||
## 검토 포인트
|
||||
|
||||
- 측정 기간과 표본 수가 없으므로 게시 전 추가한다.
|
||||
- 코드 블록과 수치는 그대로 보존한다.
|
||||
- ‘완전히 자동화했다’거나 ‘사용자 경험이 좋아졌다’는 주장은 근거가 없어 넣지 않는다.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{"id": "pair-01", "type": "opening", "source_context": "배포 평균 18분, 실패 단계 추적 불가", "before": "오늘날 빠르게 변화하는 개발 환경에서 안정적인 배포는 매우 중요합니다. 이번 글에서는 배포 개선 여정을 살펴보겠습니다.", "after": "기존 배포는 평균 18분이 걸렸고, 실패가 발생해도 어느 단계에서 멈췄는지 확인하기 어려웠다. 이 글에서는 배포 시간을 줄이고 실패 단계를 추적할 수 있도록 파이프라인을 재설계한 과정을 설명한다.", "rule_ids": ["AUD-01", "AI-01", "STR-01"]}
|
||||
{"id": "pair-02", "type": "evidence", "source_context": "API p95 420ms -> 180ms, 반복 조회 캐시", "before": "캐시를 적용해 성능과 사용자 경험을 크게 개선했습니다.", "after": "반복 조회 결과를 캐시해 데이터베이스 호출을 줄였다. 그 결과 API p95 응답 시간은 420ms에서 180ms로 감소했다.", "rule_ids": ["SRC-01", "AI-02", "CLR-01", "INV-01"]}
|
||||
{"id": "pair-03", "type": "conclusion", "source_context": "실패율 3.2% -> 0.9%, 수동 승인 잔존", "before": "이번 프로젝트는 성공적이었고 많은 것을 배웠습니다. 앞으로도 지속적으로 발전시키겠습니다.", "after": "변경 후 배포 실패율은 3.2%에서 0.9%로 줄었다. 다만 수동 승인 단계는 남아 있으며, 다음 분기에는 승인 대기 시간을 별도로 측정한다.", "rule_ids": ["AI-04", "INV-01", "STR-01"]}
|
||||
{"id": "pair-04", "type": "uncertainty", "source_context": "개발 환경에서만 빠른 경향, 운영 측정 없음", "before": "새 구조는 기존 구조보다 훨씬 빠르고 효율적입니다.", "after": "개발 환경에서는 새 구조의 응답이 더 빨라지는 경향을 관찰했다. 운영 환경의 전후 측정값은 아직 없어 성능 개선으로 단정하지 않는다.", "rule_ids": ["SRC-01", "SRC-02", "AI-02"]}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# 발견 시 자동 삭제하지 않는다. 글의 기능과 대체할 실제 정보가 있는지 확인한다.
|
||||
openings:
|
||||
- "오늘날 빠르게 변화하는"
|
||||
- "현대 사회에서"
|
||||
- "이번 글에서는 살펴보겠습니다"
|
||||
- "여정을 소개합니다"
|
||||
transitions:
|
||||
- "이를 통해"
|
||||
- "이러한 관점에서"
|
||||
- "다음과 같은 내용을 확인할 수 있습니다"
|
||||
closings:
|
||||
- "더 나은 미래를 기대합니다"
|
||||
- "많은 것을 배울 수 있었습니다"
|
||||
- "지속적으로 발전시켜 나갈 예정입니다"
|
||||
- "도움이 되기를 기대합니다"
|
||||
policy:
|
||||
- "실제 문제·관찰·결정·결과·한계로 대체할 근거가 있을 때만 수정"
|
||||
- "표현 하나만으로 AI 작성 여부를 판정하지 않음"
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# 예시 사전이다. 프로젝트의 공식 표기표가 있으면 이를 대체한다.
|
||||
terms:
|
||||
- canonical: Apache Kafka
|
||||
aliases: [Kafka, 카프카, Apache kafka]
|
||||
first_use: "Apache Kafka(이하 Kafka)"
|
||||
later_use: "Kafka"
|
||||
- canonical: Kubernetes
|
||||
aliases: [쿠버네티스, K8s]
|
||||
preserve_identifiers: true
|
||||
- canonical: Redis
|
||||
aliases: [레디스]
|
||||
preserve_identifiers: true
|
||||
- canonical: gRPC
|
||||
aliases: [GRPC, grpc]
|
||||
preserve_identifiers: true
|
||||
policy:
|
||||
- "코드와 공식 제품명은 대소문자를 보존"
|
||||
- "일반 개념의 한국어 설명은 첫 등장에만 필요할 수 있음"
|
||||
- "검색 가능성을 해치는 임의 한글화 금지"
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# 프로젝트에 맞게 복사하여 확장한다. 이 파일은 예시이며 포괄적 사전이 아니다.
|
||||
identifiers:
|
||||
- Kubernetes
|
||||
- Apache Kafka
|
||||
- Redis
|
||||
- PostgreSQL
|
||||
- Keycloak
|
||||
- OAuth 2.0
|
||||
- OpenID Connect
|
||||
- gRPC
|
||||
policies:
|
||||
official_case_sensitive: true
|
||||
preserve_inside_code: true
|
||||
do_not_translate_identifiers: true
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# 후보 표현이다. 단어 자체를 금지하지 말고 문맥과 근거를 확인한다.
|
||||
expressions:
|
||||
- text: "중요합니다"
|
||||
inspect_for: "중요한 대상·이유·영향·기준 부재"
|
||||
- text: "효율적입니다"
|
||||
inspect_for: "시간·비용·자원·절차 중 무엇이 줄었는지 부재"
|
||||
- text: "혁신적입니다"
|
||||
inspect_for: "비교 기준과 변화가 없음"
|
||||
- text: "성능이 좋아졌습니다"
|
||||
inspect_for: "지표·환경·전후 수치 부재"
|
||||
- text: "유연한 대응이 가능합니다"
|
||||
inspect_for: "어떤 변화에 어떤 방식으로 대응하는지 부재"
|
||||
- text: "사용자 경험을 개선했습니다"
|
||||
inspect_for: "관찰·지표·사용자 피드백 근거 부재"
|
||||
- text: "널리 사용될 것으로 예상됩니다"
|
||||
inspect_for: "예측 주체·범위·시점·근거 부재"
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
id: architecture-decision
|
||||
register: preserve_or_hamnida
|
||||
use_when: 아키텍처나 기술 선택의 이유와 결과를 설명할 때
|
||||
required_sections:
|
||||
- context_and_problem
|
||||
- decision_forces
|
||||
- alternatives
|
||||
- decision_and_reason
|
||||
- implementation_or_migration
|
||||
- consequences
|
||||
- limitations_and_reversal_conditions
|
||||
optional_sections:
|
||||
- diagrams
|
||||
- code_examples
|
||||
- future_options
|
||||
rules:
|
||||
do_not_turn_tradeoffs_into_benefits_only: true
|
||||
preserve_rejected_options_and_reasons: true
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
id: conversational-tech
|
||||
name: 대화형 기술 글
|
||||
register: preserve_consistent_haeyo_or_hamnida
|
||||
required_meaning:
|
||||
- reader_question
|
||||
- concrete_context
|
||||
- technical_reasoning
|
||||
- verification
|
||||
opening: reader_question_or_actual_observation
|
||||
ending: decision_and_remaining_question
|
||||
allow_humor: only_if_source_contains_it
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
id: default-formal
|
||||
register: hamnida
|
||||
use_when: 문서 유형이 특정되지 않은 일반 기술 사례
|
||||
required_sections:
|
||||
- problem_and_reader_value
|
||||
- constraints_and_goal
|
||||
- decision_or_approach
|
||||
- implementation
|
||||
- evidence_and_result
|
||||
- limitations_or_next_step
|
||||
optional_sections:
|
||||
- alternatives
|
||||
- code_examples
|
||||
- operational_notes
|
||||
rules:
|
||||
preserve_existing_consistent_register: true
|
||||
default_if_absent: 합니다체
|
||||
omit_unsupported_optional_sections: true
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
id: incident-postmortem
|
||||
register: formal
|
||||
use_when: 장애의 영향, 탐지, 복구, 원인과 재발 방지를 공개 가능한 범위에서 설명할 때
|
||||
required_sections:
|
||||
- incident_summary
|
||||
- user_impact
|
||||
- detection_and_timeline
|
||||
- technical_cause
|
||||
- contributing_factors
|
||||
- recovery
|
||||
- corrective_actions
|
||||
optional_sections:
|
||||
- what_worked
|
||||
- what_did_not_work
|
||||
- follow_up_metrics
|
||||
rules:
|
||||
blameless_system_focus: true
|
||||
preserve_uncertainty: true
|
||||
never_expose_sensitive_or_unpublished_details: true
|
||||
do_not_name_individuals_unless_required_and_authorized: true
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
id: migration-case-study
|
||||
register: preserve_or_hamnida
|
||||
use_when: 데이터, 플랫폼, 프레임워크, 인프라 또는 API 이관 과정을 설명할 때
|
||||
required_sections:
|
||||
- why_migration_was_needed
|
||||
- source_and_target_constraints
|
||||
- migration_strategy
|
||||
- validation_and_rollback
|
||||
- rollout
|
||||
- result_and_remaining_risk
|
||||
optional_sections:
|
||||
- data_backfill
|
||||
- compatibility_layer
|
||||
- operational_checklist
|
||||
rules:
|
||||
explain_invisible_work_value_early: true
|
||||
preserve_failure_and_rollback_conditions: true
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
id: performance-case-study
|
||||
register: preserve_or_hamnida
|
||||
use_when: 응답 시간, 처리량, 오류율, 자원 사용량 등 전후 성능을 설명할 때
|
||||
required_sections:
|
||||
- baseline_and_problem
|
||||
- metric_definition
|
||||
- environment_and_conditions
|
||||
- hypotheses_and_changes
|
||||
- before_after_results
|
||||
- regressions_and_limitations
|
||||
optional_sections:
|
||||
- failed_attempts
|
||||
- dashboards
|
||||
- code_or_query
|
||||
rules:
|
||||
put_key_result_in_first_15_percent: true
|
||||
never_report_metric_without_scope: true
|
||||
keep_adverse_results: true
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
id: recruitment-tech-content
|
||||
name: 팀·채용 기술 콘텐츠
|
||||
required_meaning:
|
||||
- systems_and_problem_types
|
||||
- role_and_ownership
|
||||
- collaboration_boundaries
|
||||
- real_technical_challenges
|
||||
forbid:
|
||||
- unverifiable_superlatives
|
||||
- invented_scale
|
||||
- promotional_exclamation_as_substitute_for_information
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
id: tooling-adoption
|
||||
register: preserve_or_hamnida
|
||||
use_when: 새로운 개발 도구, 플랫폼, 자동화 또는 AI 도구의 도입 과정을 설명할 때
|
||||
required_sections:
|
||||
- original_problem
|
||||
- evaluation_criteria
|
||||
- options_or_prior_approach
|
||||
- pilot_or_architecture
|
||||
- workflow
|
||||
- observed_results
|
||||
- costs_and_limits
|
||||
optional_sections:
|
||||
- rollout_plan
|
||||
- governance
|
||||
- security_review
|
||||
rules:
|
||||
distinguish_expectation_from_observation: true
|
||||
do_not_claim_productivity_without_measurement: true
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
id: tutorial-lab
|
||||
name: 명령어 기반 구성 실습
|
||||
required_meaning:
|
||||
- target_end_state
|
||||
- prerequisites_and_versions
|
||||
- commands_in_order
|
||||
- purpose_of_each_command
|
||||
- expected_observations
|
||||
- verification
|
||||
- cleanup_or_rollback
|
||||
- common_failures_and_diagnosis
|
||||
forbid:
|
||||
- claiming_unexecuted_commands_succeeded
|
||||
- omitting_destructive_command_warnings
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
# 판단 우선순위와 불변식
|
||||
|
||||
## 우선순위
|
||||
|
||||
1. 사실·법무·보안·코드·직접 인용
|
||||
2. 사용자 요구와 프로젝트·기업의 공식 가이드
|
||||
3. 공식 제품명과 프로젝트 용어
|
||||
4. 한국어 어문 규범
|
||||
5. 기술 독자의 이해와 접근성
|
||||
6. 기술 블로그 장르 구조
|
||||
7. AI 유사 문체 완화
|
||||
8. 미적 변주와 개성 강화
|
||||
|
||||
하위 규칙이 상위 규칙을 침해하면 하위 수정을 취소한다.
|
||||
|
||||
## 불변식
|
||||
|
||||
- 긍정·부정, 조건, 예외, 시제, 시간 순서
|
||||
- 가능성·권고·의무·확정의 강도
|
||||
- 주체, 객체, 책임 범위와 1인칭 관점
|
||||
- 수치, 단위, 날짜, 버전, 오류 코드와 지표 정의
|
||||
- 기술 선택의 이유, 비교한 대안, 비용과 위험
|
||||
- 실험 환경, 표본, 미측정 상태와 불확실성
|
||||
- 제품명, 기술명, API·클래스·함수·설정 키
|
||||
- 코드, 명령어, URL, 직접 인용, 법무·보안 문구
|
||||
- 마크다운의 코드 블록, 표, 목록과 링크 구조
|
||||
|
||||
## 즉시 실패
|
||||
|
||||
- 원문에 없는 수치·성과·사례·감정·사용자 반응 생성
|
||||
- 코드·명령어·법무 문구·직접 인용 변경
|
||||
- 민감 정보 또는 미공개 정보를 그대로 공개
|
||||
- 불리한 결과, 실패 조건, 비용 또는 위험 삭제
|
||||
- 미측정 결과를 검증된 결과처럼 작성
|
||||
- 작성 주체가 불명확한데 임의로 개인이나 팀에 책임 부여
|
||||
|
||||
## 정보 부족
|
||||
|
||||
- 글의 목적·독자·문서 유형이 없어도 안전한 기본값으로 진행할 수 있으면 가정 목록에 기록한다.
|
||||
- 사실 여부나 구조를 바꾸는 필수 정보가 없으면 한 번에 필요한 최소 질문만 하거나 `[확인 필요]`로 남긴다.
|
||||
- 선택적인 배경·회고·성과 정보가 없으면 해당 섹션을 생략한다.
|
||||
- 자료끼리 충돌하면 더 높은 우선순위의 출처를 사용하고 충돌을 경고한다.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
# 기업 기술 블로그에서 재현할 구조적 패턴
|
||||
|
||||
이 문서는 특정 기업의 문체를 모방하기 위한 자료가 아니다. 업로드된 연구가 NAVER D2, 카카오, LINE, 우아한형제들, 삼성SDS의 공개 글에서 추출한 **구조적 특징**만 일반화한다.
|
||||
|
||||
## 재현할 가치가 큰 패턴
|
||||
|
||||
- `성능이 좋아졌다`보다 지표 정의와 전후 수치를 제시한다.
|
||||
- 측정·관찰 단계와 개선·적용 단계를 분리한다.
|
||||
- 도입 계기에서 아키텍처와 실제 시나리오까지 독자의 판단 순서로 전개한다.
|
||||
- 정량 목표를 먼저 정하고 분석·조치·재측정으로 이어 간다.
|
||||
- 여러 시도를 하나의 묘책처럼 합치지 않고 각 가설과 결과를 분리한다.
|
||||
- 성공 결과뿐 아니라 테스트 설계, 운영 비용, 실패 조건과 교훈을 남긴다.
|
||||
- 실험 환경과 비교 기준을 공개해 수치의 적용 범위를 드러낸다.
|
||||
- 사용자 화면에 보이지 않는 이관·인프라 작업은 왜 필요했는지부터 설명한다.
|
||||
- 기존 기술의 기대 효과와 실제 워크로드에서 얻지 못한 효과를 대조한다.
|
||||
- 표와 참고문헌은 핵심 명제를 검증 가능하게 만드는 경우에만 사용한다.
|
||||
|
||||
## 피해야 할 패턴
|
||||
|
||||
- 추상적인 미래·혁신 은유로 결론을 대신함
|
||||
- 범위·시점·근거가 없는 전망
|
||||
- 한 문장에 개발·품질·위험·확장성 효과를 모두 중첩
|
||||
- `도움이 되기를 기대합니다` 같은 의례적 마무리
|
||||
- 검증 불가능한 최상급과 감탄 표현
|
||||
- 브랜드 친근함을 이유로 기술적 경고나 비용을 약화
|
||||
|
||||
## 브랜드 적용
|
||||
|
||||
프로젝트의 명시적 스타일 가이드가 있으면 이를 우선한다. 가이드가 없으면 다른 기업의 어휘·유머·말투를 흉내 내지 않고, 정확·명료·절제된 기본 문체를 사용한다.
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# 근거와 출처 처리
|
||||
|
||||
## 주장 유형
|
||||
|
||||
각 핵심 문장을 다음 중 하나로 분류한다.
|
||||
|
||||
| 유형 | 의미 | 작성 방식 |
|
||||
|---|---|---|
|
||||
| source | 제공된 자료에 직접 있음 | 자료의 범위와 표현 강도를 유지 |
|
||||
| external | 외부 출처가 있음 | 출처와 적용 범위를 함께 표시 |
|
||||
| observed | 작성자 또는 팀이 관찰함 | 환경·기간·측정 방법을 함께 기록 |
|
||||
| inferred | 자료를 바탕으로 추론함 | 추론임을 명시하고 근거를 연결 |
|
||||
| unverified | 아직 확인하지 않음 | `[확인 필요]`, 미측정 또는 예정으로 표시 |
|
||||
|
||||
## 근거 지도
|
||||
|
||||
초안 전 최소한 다음 표를 내부적으로 만든다.
|
||||
|
||||
```text
|
||||
주장 | 근거 위치 | 신뢰 수준 | 보호 요소 | 공개 가능 여부
|
||||
```
|
||||
|
||||
정량 주장은 수치만 남기지 말고 지표 정의, 측정 기간, 환경, 비교 기준과 제외 조건을 가능한 범위에서 함께 기록한다.
|
||||
|
||||
## 외부 자료
|
||||
|
||||
사용자가 외부 조사나 검증을 요청하지 않았다면 제공된 자료 밖의 지식을 사실처럼 채우지 않는다. 외부 조사를 수행했다면 소스 기반 내용과 외부 조사 내용을 분리하고 인용을 붙인다.
|
||||
|
||||
## 코드와 명령어
|
||||
|
||||
- 코드와 명령어는 자연어 편집 대상에서 제외한다.
|
||||
- 실행 결과가 제공되지 않았으면 `검증했다`, `정상 동작한다`고 쓰지 않는다.
|
||||
- 코드 설명은 코드가 실제로 하는 일을 넘어서지 않는다.
|
||||
- 예제 코드가 축약되거나 의사 코드이면 그 사실을 표시한다.
|
||||
|
||||
## 민감 정보
|
||||
|
||||
계정, 비밀 키, 토큰, 내부 도메인·IP, 개인정보, 미공개 장애 정보, 고객 식별자는 공개 글에 포함하지 않는다. 자동 마스킹으로 의미가 손상될 수 있으면 `blocked` 상태와 필요한 조치를 반환한다.
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# 경계와 예외
|
||||
|
||||
| 상황 | 잘못된 처리 | 올바른 처리 |
|
||||
|---|---|---|
|
||||
| 성능이 좋아졌지만 수치 없음 | 임의의 백분율 추가 | 관찰 환경과 미측정 상태 명시 |
|
||||
| 행위자 미확정 | 능동태를 위해 운영자 지정 | 피동을 유지하고 주체 미확정 표시 |
|
||||
| 직접 인용에 구어체·오탈자 | 기술 문체로 바꿈 | 인용문은 보존하고 밖에서 설명 |
|
||||
| 코드 주석의 비표준 표현 | 코드와 함께 자동 교정 | 실행 코드 보호, 변경 허용된 자연어 주석만 별도 검토 |
|
||||
| 영문 기술명 혼용 | 임의로 한글화 | 공식 표기 확인, 불가하면 첫 표기 유지 + 경고 |
|
||||
| 해요체 원문 | 무조건 합니다체로 통일 | 일관된 원문 말투 유지 |
|
||||
| 감성적 글을 요청 | 경험·감정 창작 | 자료에 있는 관찰과 감정만 사용 |
|
||||
| 핵심 용어 반복 | 동의어로 무작위 변경 | 기술 용어는 유지하고 주변 구조를 조정 |
|
||||
| 결론 중복 제거 | 한계·재발 방지까지 삭제 | 단순 재요약만 줄임 |
|
||||
| 보안·장애 공지 | 친근함을 위해 심각성 완화 | 위험 전달과 정확성 우선 |
|
||||
|
||||
## 질문 대신 진행할 수 있는 경우
|
||||
|
||||
- 독자가 미지정이면 기본 독자 가정을 밝히고 진행
|
||||
- 말투가 미지정이면 원문을 유지하거나 기본 합니다체 사용
|
||||
- 선택 절의 정보가 없으면 생략
|
||||
- 일부 근거만 부족하면 해당 주장에 `확인 필요`를 붙이고 나머지 작성
|
||||
|
||||
## 중단 또는 차단할 경우
|
||||
|
||||
- 핵심 수치나 결과가 서로 충돌함
|
||||
- 소스에 없는 주장을 반드시 사실처럼 쓰라고 요구함
|
||||
- 공개하면 안 되는 정보가 글의 핵심임
|
||||
- 법적 고지나 인용을 변조해야만 요청을 만족함
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
# 출력 모드
|
||||
|
||||
## article — 기본
|
||||
|
||||
완성된 제목과 본문을 먼저 제공한다. 근거 부족이나 공개 위험이 있을 때만 짧은 경고를 덧붙인다.
|
||||
|
||||
## outline
|
||||
|
||||
자료를 쓰지 않고 다음을 출력한다.
|
||||
|
||||
- 글의 목적과 독자
|
||||
- 핵심 주장과 근거
|
||||
- 선택한 프로필
|
||||
- 제목 후보
|
||||
- 섹션별 메시지와 필요한 자료
|
||||
- 확인이 필요한 항목
|
||||
|
||||
## audit
|
||||
|
||||
원문을 수정하지 않는다. 구조, 근거, 불변식, 보호 구간, 기술적 설명력, 문체 위험과 공개 위험을 심각도순으로 진단한다.
|
||||
|
||||
## revision
|
||||
|
||||
수정본을 먼저 제시하고 주요 변경을 `문제 → 수정 → 규칙 ID → 보존 확인` 형식으로 기록한다.
|
||||
|
||||
## compare
|
||||
|
||||
원문과 수정문을 대응시켜 보여 준다. 문장 전체를 모두 설명하지 않고 의미 있는 구조·근거·보존 관련 변경만 기록한다.
|
||||
|
||||
## publication-package
|
||||
|
||||
요청이 있을 때만 다음을 포함한다.
|
||||
|
||||
- 제목 3개 이하
|
||||
- 한 문단 요약
|
||||
- 본문
|
||||
- 메타 설명
|
||||
- 태그 후보
|
||||
- 근거·인용 목록
|
||||
- 공개 전 확인 항목
|
||||
|
||||
SEO 키워드 반복, 클릭 유도형 제목, 근거 없는 성과 문구는 추가하지 않는다.
|
||||
|
||||
## 상태
|
||||
|
||||
- `pass`: 자료 범위 안에서 결과를 작성함
|
||||
- `needs_clarification`: 필수 사실 또는 공개 범위가 불명확함
|
||||
- `blocked`: 민감 정보, 법무·보안 위험 또는 보호 구간 훼손 없이는 작성할 수 없음
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
# 규칙 카탈로그
|
||||
|
||||
이 문서는 스킬의 판단 규칙과 테스트 ID를 연결한다. 규칙 충돌 시 `references/decision-policy.md`의 우선순위를 따른다.
|
||||
|
||||
### INV-01 — 수치·날짜·버전·단위 보존
|
||||
원문에서 숫자와 대응 대상을 추출하고 출력에서 같은 관계를 유지한다. 값, 방향, 단위, 기간을 임의로 바꾸지 않는다.
|
||||
|
||||
### INV-02 — 보호 구간 잠금
|
||||
코드 블록, 인라인 코드, 명령어, URL, 직접 인용, 법무·보안 문구, 사용자가 잠근 문자열은 정확히 보존한다.
|
||||
|
||||
### INV-03 — 공식 용어 표기표
|
||||
제품명, 기술명, 팀명, 약어와 식별자의 기준 표기를 먼저 정하고 글 전체에서 일관되게 사용한다.
|
||||
|
||||
### SRC-01 — 원문 밖 사실 생성 금지
|
||||
자료에 없는 성과, 원인, 사용자 반응, 업계 추세, 감정과 경험을 만들지 않는다.
|
||||
|
||||
### SRC-02 — 미지정 정보의 명시
|
||||
필수 정보가 없으면 `[확인 필요: ...]`, 미지정, 미측정 또는 질문으로 남긴다. 선택 섹션은 생략한다.
|
||||
|
||||
### AUD-01 — 목적·독자·독자 결과 확인
|
||||
글을 쓰기 전에 왜 쓰는지, 누가 읽는지, 읽고 무엇을 이해하거나 결정해야 하는지 고정한다.
|
||||
|
||||
### STR-01 — 기술 사례 기본 골격
|
||||
자료가 뒷받침하는 범위에서 문제·맥락 → 제약·대안 → 선택 → 구현·실험 → 결과 → 한계·후속 조치로 구성한다.
|
||||
|
||||
### STR-02 — 핵심 결과의 조기 제시
|
||||
결과 수치가 글의 핵심이면 첫 15% 안의 요약이나 도입에 배치하고 측정 환경과 함께 제시한다.
|
||||
|
||||
### STR-03 — 대상과 행동이 드러나는 제목
|
||||
`소개`, `살펴보기`, `여정`만으로 제목을 만들지 않는다. 대상, 문제, 선택 또는 결과를 제목에 드러낸다.
|
||||
|
||||
### KOR-01 — 한국어 규범 최종 검수
|
||||
초안과 문체 편집이 끝난 뒤 `editing-korean-grammar-and-expression`으로 맞춤법·띄어쓰기·문장 부호를 검수한다.
|
||||
|
||||
### KOR-02 — 문장 호응과 수식 범위
|
||||
주어·목적어·서술어의 호응을 확인하고 독립 주장·조건·결론이 한 문장에 과도하게 중첩되면 의미를 보존해 분리한다.
|
||||
|
||||
### KOR-03 — 식별자와 일반 개념 구분
|
||||
코드 식별자와 공식 제품명은 원문을 보존한다. 일반 기술 개념은 필요할 때 첫 등장에 한국어 설명을 붙인다.
|
||||
|
||||
### CLR-01 — 주체와 동작 우선
|
||||
추상 명사와 막연한 평가보다 누가 무엇을 했고 어떤 영향이 있었는지 쓴다. 근거가 없으면 구체화를 보류한다.
|
||||
|
||||
### CLR-02 — 복합 문장 분리
|
||||
독립 주장·조건·결론이 셋 이상이거나 검증 관계가 흐려지면 문장을 나누거나 표·목록으로 옮긴다.
|
||||
|
||||
### CLR-03 — 모호한 지시어 복원
|
||||
`이를`, `이러한`, `해당`, `이것`의 선행 대상이 불명확하면 자료에 있는 구체 명사를 복원한다.
|
||||
|
||||
### AI-01 — 실제 문제로 시작
|
||||
시대 일반론, 의례적 인사, 글쓰기 행위 설명보다 시스템의 문제, 관찰값, 목표 또는 독자가 얻을 정보를 먼저 제시한다.
|
||||
|
||||
### AI-02 — 평가어를 근거로 대체
|
||||
`중요하다`, `효율적이다`, `혁신적이다`, `빠르다`는 지표·작동 방식·영향·비교 기준이 있을 때만 사용한다.
|
||||
|
||||
### AI-03 — 구조와 문장 틀 반복 완화
|
||||
접속어와 종결형을 무작위로 바꾸지 않는다. 실제 인과·시간·비교 관계에 맞춰 반복을 줄인다.
|
||||
|
||||
### AI-04 — 결과·한계 중심 결론
|
||||
결론은 본문 재요약이나 의례적 기대보다 결정, 검증 결과, 적용 조건, 남은 문제와 다음 검증을 제시한다.
|
||||
|
||||
### AI-05 — 인간 흉내 금지
|
||||
자연스럽게 보이게 하려고 오탈자, 비문, 감정, 실패담, 사적 일화나 확신을 만들지 않는다.
|
||||
|
||||
### BRD-01 — 프로젝트·기업 프로필 우선
|
||||
명시된 브랜드 가이드가 있으면 우선한다. 없으면 다른 기업을 모방하지 않고 정확·명료·절제된 기본 프로필을 사용한다.
|
||||
|
||||
### REV-01 — 변경 근거 기록
|
||||
수정 모드에서는 주요 변경마다 문제, 수정 결과, 규칙 ID, 보존 확인과 필요한 경고를 기록한다.
|
||||
|
||||
### TST-01 — 하드 게이트와 회귀 검증
|
||||
사실 변경, 보호 구간 변경, 허위 근거, 보안 노출은 점수와 무관하게 실패다. 일반·어려운·회귀 사례를 모두 검증한다.
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# 자료 근거
|
||||
|
||||
이 스킬은 사용자가 제공한 연구 문서 `붙여넣은 마크다운(1)(2).md`의 내용을 기반으로 구성했다. 문서에 포함된 다음 범주의 자료와 사례를 규칙·프로필·테스트로 변환했다.
|
||||
|
||||
- 국립국어원 한국어 어문 규범, 맞춤법·표준어·문장 부호·공공언어 자료
|
||||
- 토스의 라이팅 원칙, 테크니컬 라이팅 Skill 구현과 Skill 품질 루브릭 사례
|
||||
- Google Developer Documentation Style Guide
|
||||
- Microsoft Writing Style Guide
|
||||
- 한국어 LLM 문체 관련 ACL 2025 연구
|
||||
- NAVER D2, 카카오, LINE, 우아한형제들, 삼성SDS의 공개 기술 글 사례 분석
|
||||
|
||||
## 출처 계층
|
||||
|
||||
1. 사실·법무·보안·코드·직접 인용
|
||||
2. 프로젝트 또는 기업의 명시적 가이드
|
||||
3. 공식 제품명과 기술 용어
|
||||
4. 국립국어원 공식 규범
|
||||
5. 기술 독자의 이해와 접근성
|
||||
6. 기술 블로그 장르 관습
|
||||
7. AI 유사 문체 완화
|
||||
8. 미적 변주
|
||||
|
||||
## 원문이 제시한 주요 링크
|
||||
|
||||
- https://korean.go.kr/kornorms
|
||||
- https://developers.google.com/style
|
||||
- https://learn.microsoft.com/en-us/style-guide/welcome/
|
||||
- https://toss.tech/article/8-writing-principles-of-toss
|
||||
- https://toss.tech/article/technical-writing-5
|
||||
- https://toss.tech/article/skill-quality-rubric
|
||||
- https://aclanthology.org/2025.acl-long.1030/
|
||||
- https://aclanthology.org/2025.acl-long.267/
|
||||
|
||||
이 패키지는 링크의 최신 상태나 원 연구의 해석을 별도로 재검증하지 않았다. 스킬 내용은 업로드된 연구가 정리한 범위에 한정된다.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# 기술 블로그 구조 패턴
|
||||
|
||||
목차를 고정 템플릿처럼 강제하지 않는다. 독자가 따라야 할 의사결정 순서를 기준으로 프로필을 선택한다.
|
||||
|
||||
## 공통 골격
|
||||
|
||||
1. 문제 또는 관찰값
|
||||
2. 왜 지금 해결해야 했는지
|
||||
3. 제약과 성공 기준
|
||||
4. 검토한 대안과 선택 이유
|
||||
5. 구현·실험 또는 운영 방식
|
||||
6. 검증 방법과 결과
|
||||
7. 비용·한계·실패 조건
|
||||
8. 남은 과제와 적용 조건
|
||||
|
||||
자료가 없는 섹션은 만들지 않는다. 결과가 핵심이면 도입부에서 먼저 보여 주고 뒤에서 측정 방법을 설명한다.
|
||||
|
||||
## 도입
|
||||
|
||||
첫 15% 안에 다음 중 필요한 내용을 드러낸다.
|
||||
|
||||
- 어떤 시스템이나 작업을 다루는지
|
||||
- 실제 문제 또는 관찰값
|
||||
- 독자가 얻을 수 있는 정보
|
||||
- 핵심 결과와 측정 범위
|
||||
|
||||
피해야 할 시작은 시대 일반론, 의례적 인사, `이번 글에서는 살펴보겠습니다`뿐인 문장이다.
|
||||
|
||||
## 제목
|
||||
|
||||
제목은 대상·문제·행동·선택·결과 중 하나 이상을 담는다.
|
||||
|
||||
```text
|
||||
나쁨: Kubernetes 배포 자동화 소개
|
||||
개선: Kubernetes 배포에서 승인·롤백·상태 확인을 자동화한 방법
|
||||
```
|
||||
|
||||
숫자를 제목에 넣을 때는 본문이 같은 측정 기준을 뒷받침해야 한다.
|
||||
|
||||
## 본문
|
||||
|
||||
- 기술 선택은 장점 목록보다 제약과 대안 비교로 설명한다.
|
||||
- 실험은 환경, 입력, 지표, 전후 조건을 분리한다.
|
||||
- 여러 시도는 가설·조치·결과를 각각 묶는다.
|
||||
- 보이지 않는 인프라 작업은 `왜 해야 했는가`부터 설명한다.
|
||||
- 구현 세부는 독자가 재현하거나 판단하는 데 필요한 수준까지만 포함한다.
|
||||
|
||||
## 결론
|
||||
|
||||
결론은 본문을 다시 요약하는 대신 다음을 선택한다.
|
||||
|
||||
- 실제 결과와 측정 범위
|
||||
- 선택이 유효한 조건
|
||||
- 남은 비용과 위험
|
||||
- 실패한 가설 또는 얻은 교훈
|
||||
- 다음에 측정하거나 바꿀 항목
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# 제목·도입·결론
|
||||
|
||||
## 제목
|
||||
|
||||
대상과 행동 또는 갈등을 드러낸다.
|
||||
|
||||
| 약한 제목 | 개선 방향 |
|
||||
|---|---|
|
||||
| Kubernetes 살펴보기 | Kubernetes로 배포 롤백을 자동화한 방법 |
|
||||
| 성능 개선 이야기 | 검색 API p95를 420ms에서 180ms로 줄인 과정 |
|
||||
| Kafka 도입기 | 장시간 작업에서 Kafka 대신 RDB Task Queue를 선택한 이유 |
|
||||
|
||||
수치 제목은 근거와 범위가 명확할 때만 사용한다.
|
||||
|
||||
## 도입
|
||||
|
||||
첫 15% 안에 다음 세 가지를 드러낸다.
|
||||
|
||||
1. 어떤 시스템·작업에서 무슨 문제가 있었는가
|
||||
2. 왜 독자에게 중요한가 또는 어떤 제약이 있었는가
|
||||
3. 글을 읽으면 무엇을 알 수 있는가
|
||||
|
||||
시대 일반론, 의례적 인사, ‘여정을 살펴보겠다’는 메타 문장으로 시작하지 않는다.
|
||||
|
||||
## 소제목
|
||||
|
||||
`소개`, `배경`, `내용`, `결론`만 쓰지 말고 절의 판단이나 동작을 표현한다.
|
||||
|
||||
- `배경` → `배포가 18분 걸린 이유`
|
||||
- `구현` → `실패 단계를 분리해 로그를 남기기`
|
||||
- `결과` → `평균 배포 시간은 줄었지만 승인 대기는 남았다`
|
||||
|
||||
## 결론
|
||||
|
||||
다음 중 실제 자료가 있는 항목으로 끝낸다.
|
||||
|
||||
- 어떤 결정을 내렸는가
|
||||
- 어떤 결과를 어떤 조건에서 확인했는가
|
||||
- 무엇은 해결하지 못했는가
|
||||
- 어디까지 적용 가능한가
|
||||
- 다음에 무엇을 측정하거나 바꿀 것인가
|
||||
|
||||
본문을 다시 요약하거나 ‘더 나은 미래’, ‘많은 것을 배웠다’, ‘지속적으로 발전시키겠다’로 끝내지 않는다.
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "Korean Technical Blog Brief",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"sources"
|
||||
],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"enum": [
|
||||
"outline",
|
||||
"article",
|
||||
"revise",
|
||||
"audit"
|
||||
],
|
||||
"default": "article"
|
||||
},
|
||||
"document_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"purpose": {
|
||||
"type": "string"
|
||||
},
|
||||
"target_audience": {
|
||||
"type": "string"
|
||||
},
|
||||
"reader_outcome": {
|
||||
"type": "string"
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"content"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"source_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"verified": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"claim": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {},
|
||||
"scope": {
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"enum": [
|
||||
"verified",
|
||||
"unverified",
|
||||
"conflicting"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"protected_terms": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"locked_spans": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"register": {
|
||||
"enum": [
|
||||
"preserve",
|
||||
"hamnida",
|
||||
"haeyo",
|
||||
"plain"
|
||||
]
|
||||
},
|
||||
"public_constraints": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "KoreanTechnicalBlogResult",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"status",
|
||||
"document_type",
|
||||
"assumptions",
|
||||
"protected_spans",
|
||||
"article",
|
||||
"changes",
|
||||
"warnings",
|
||||
"scores",
|
||||
"gate_failures"
|
||||
],
|
||||
"properties": {
|
||||
"status": {
|
||||
"enum": [
|
||||
"pass",
|
||||
"needs_clarification",
|
||||
"blocked"
|
||||
]
|
||||
},
|
||||
"document_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"assumptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"field",
|
||||
"value",
|
||||
"state"
|
||||
],
|
||||
"properties": {
|
||||
"field": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {},
|
||||
"state": {
|
||||
"enum": [
|
||||
"provided",
|
||||
"inferred",
|
||||
"unspecified"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"protected_spans": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"article": {
|
||||
"type": "string"
|
||||
},
|
||||
"changes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"source",
|
||||
"result",
|
||||
"problem",
|
||||
"rule_ids",
|
||||
"preservation_check"
|
||||
],
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"result": {
|
||||
"type": "string"
|
||||
},
|
||||
"problem": {
|
||||
"type": "string"
|
||||
},
|
||||
"rule_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"preservation_check": {
|
||||
"enum": [
|
||||
"passed",
|
||||
"warning",
|
||||
"failed"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scores": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"factual_fidelity",
|
||||
"structure_and_audience",
|
||||
"korean_language",
|
||||
"technical_evidence",
|
||||
"brand_consistency",
|
||||
"naturalness",
|
||||
"total"
|
||||
],
|
||||
"properties": {
|
||||
"factual_fidelity": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"structure_and_audience": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"korean_language": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"technical_evidence": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"brand_consistency": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"naturalness": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"total": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"gate_failures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "KoreanTechnicalBlogRubric",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"case_id",
|
||||
"hard_gate_passed",
|
||||
"scores",
|
||||
"total",
|
||||
"verdict",
|
||||
"notes"
|
||||
],
|
||||
"properties": {
|
||||
"case_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"hard_gate_passed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"scores": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"factual_fidelity",
|
||||
"structure_and_audience",
|
||||
"korean_language",
|
||||
"technical_evidence",
|
||||
"brand_consistency",
|
||||
"naturalness"
|
||||
],
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 100
|
||||
},
|
||||
"verdict": {
|
||||
"enum": [
|
||||
"pass",
|
||||
"fail",
|
||||
"needs_review"
|
||||
]
|
||||
},
|
||||
"notes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
Executable
+227
@@ -0,0 +1,227 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REQUIRED = [
|
||||
ROOT / "SKILL.md",
|
||||
ROOT / "README.md",
|
||||
ROOT / "references" / "decision-policy.md",
|
||||
ROOT / "references" / "evidence-and-source-policy.md",
|
||||
ROOT / "references" / "enterprise-blog-patterns.md",
|
||||
ROOT / "references" / "exceptions.md",
|
||||
ROOT / "references" / "output-modes.md",
|
||||
ROOT / "references" / "rule-catalog.md",
|
||||
ROOT / "references" / "source-basis.md",
|
||||
ROOT / "references" / "structure-patterns.md",
|
||||
ROOT / "references" / "titles-introductions-conclusions.md",
|
||||
ROOT / "profiles" / "default-formal.yaml",
|
||||
ROOT / "profiles" / "performance-case-study.yaml",
|
||||
ROOT / "profiles" / "architecture-decision.yaml",
|
||||
ROOT / "profiles" / "migration-case-study.yaml",
|
||||
ROOT / "profiles" / "incident-postmortem.yaml",
|
||||
ROOT / "profiles" / "tooling-adoption.yaml",
|
||||
ROOT / "profiles" / "conversational-tech.yaml",
|
||||
ROOT / "profiles" / "recruitment-tech-content.yaml",
|
||||
ROOT / "profiles" / "tutorial-lab.yaml",
|
||||
ROOT / "lexicons" / "vague-expressions.yaml",
|
||||
ROOT / "lexicons" / "formulaic-openings-and-closings.yaml",
|
||||
ROOT / "lexicons" / "product-names.example.yaml",
|
||||
ROOT / "lexicons" / "protected-identifiers.example.yaml",
|
||||
ROOT / "examples" / "revision-pairs.jsonl",
|
||||
ROOT / "examples" / "end-to-end-performance-case.md",
|
||||
ROOT / "tests" / "baseline-observations.md",
|
||||
ROOT / "tests" / "cases.json",
|
||||
ROOT / "tests" / "evaluation-rubric.md",
|
||||
ROOT / "tests" / "pressure-scenarios.md",
|
||||
ROOT / "tests" / "workflow.jsonl",
|
||||
ROOT / "schemas" / "article-brief.schema.json",
|
||||
ROOT / "schemas" / "article-result.schema.json",
|
||||
ROOT / "schemas" / "rubric.schema.json",
|
||||
]
|
||||
|
||||
|
||||
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")
|
||||
try:
|
||||
data = yaml.safe_load(match.group(1))
|
||||
except yaml.YAMLError as exc:
|
||||
fail(f"invalid SKILL.md frontmatter: {exc}")
|
||||
if not isinstance(data, dict):
|
||||
fail("frontmatter must be an object")
|
||||
for key in ("name", "description"):
|
||||
if not isinstance(data.get(key), str) or not data[key].strip():
|
||||
fail(f"frontmatter is missing non-empty {key!r}")
|
||||
return {"name": data["name"].strip(), "description": data["description"].strip()}
|
||||
|
||||
|
||||
def read_jsonl(path: Path) -> list[dict]:
|
||||
records: list[dict] = []
|
||||
for line_number, raw in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
|
||||
if not raw.strip():
|
||||
continue
|
||||
try:
|
||||
value = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
fail(f"invalid JSONL in {path.name}:{line_number}: {exc}")
|
||||
if not isinstance(value, dict):
|
||||
fail(f"JSONL record must be object in {path.name}:{line_number}")
|
||||
records.append(value)
|
||||
if not records:
|
||||
fail(f"JSONL file is empty: {path.name}")
|
||||
return records
|
||||
|
||||
|
||||
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["name"]
|
||||
description = frontmatter["description"]
|
||||
if name != ROOT.name:
|
||||
fail(f"frontmatter name {name!r} must match directory {ROOT.name!r}")
|
||||
if not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", name):
|
||||
fail("name must use lowercase letters, numbers, and hyphens only")
|
||||
if len(name) > 64:
|
||||
fail("name exceeds 64 characters")
|
||||
if not description.startswith("Use when "):
|
||||
fail("description must start with 'Use when '")
|
||||
if len((name + description).encode("utf-8")) > 1024:
|
||||
fail("name + description exceeds 1024 bytes")
|
||||
words = len(skill_text.split())
|
||||
if words > 500:
|
||||
fail(f"SKILL.md exceeds 500 words: {words}")
|
||||
if "cite" in skill_text or "filecite" in skill_text or re.search(r"turn\d+(?:view|search|file)\d+", skill_text):
|
||||
fail("runtime-specific citation markers must not appear in SKILL.md")
|
||||
for dependency in ("reducing-ai-like-korean-writing", "editing-korean-grammar-and-expression"):
|
||||
if dependency not in skill_text:
|
||||
fail(f"SKILL.md must declare required sub-skill {dependency}")
|
||||
|
||||
catalog = (ROOT / "references" / "rule-catalog.md").read_text(encoding="utf-8")
|
||||
known_rules = set(re.findall(r"(?m)^###\s+([A-Z]+-\d{2})\s+—", catalog))
|
||||
if len(known_rules) < 20:
|
||||
fail(f"rule catalog too small: {len(known_rules)}")
|
||||
|
||||
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")
|
||||
required_keys = {
|
||||
"id", "category", "mode", "profile", "request", "source_material",
|
||||
"expected_status", "reference_output", "must_include", "must_not_include",
|
||||
"preserve_exact", "rule_ids", "manual_criteria",
|
||||
}
|
||||
allowed_categories = {"general", "hard", "regression"}
|
||||
allowed_status = {"pass", "needs_clarification", "blocked"}
|
||||
ids: set[str] = set()
|
||||
used_rules: set[str] = set()
|
||||
for index, case in enumerate(cases):
|
||||
if not isinstance(case, dict):
|
||||
fail(f"case #{index} must be an object")
|
||||
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["category"] not in allowed_categories:
|
||||
fail(f"invalid category in {case['id']}")
|
||||
if case["expected_status"] not in allowed_status:
|
||||
fail(f"invalid expected_status in {case['id']}")
|
||||
if not isinstance(case["rule_ids"], list) or not case["rule_ids"]:
|
||||
fail(f"rule_ids must be a non-empty array in {case['id']}")
|
||||
unknown = set(case["rule_ids"]) - known_rules
|
||||
if unknown:
|
||||
fail(f"unknown rule IDs in {case['id']}: {sorted(unknown)}")
|
||||
used_rules.update(case["rule_ids"])
|
||||
for key in ("must_include", "must_not_include", "preserve_exact", "manual_criteria"):
|
||||
if not isinstance(case[key], list):
|
||||
fail(f"{key} must be an array in {case['id']}")
|
||||
reference = case["reference_output"]
|
||||
for text in case["must_include"]:
|
||||
if text not in reference:
|
||||
fail(f"must_include missing from reference_output in {case['id']}: {text!r}")
|
||||
for text in case["must_not_include"]:
|
||||
if text in reference:
|
||||
fail(f"must_not_include present in reference_output in {case['id']}: {text!r}")
|
||||
for text in case["preserve_exact"]:
|
||||
if text not in case["source_material"] or text not in reference:
|
||||
fail(f"preserve_exact must exist in source and reference in {case['id']}: {text!r}")
|
||||
|
||||
uncovered = known_rules - used_rules
|
||||
if uncovered:
|
||||
fail(f"rule IDs without test coverage: {sorted(uncovered)}")
|
||||
|
||||
categories = {c: sum(1 for x in cases if x["category"] == c) for c in allowed_categories}
|
||||
if categories["general"] < 10 or categories["hard"] < 7 or categories["regression"] < 5:
|
||||
fail(f"insufficient test category counts: {categories}")
|
||||
|
||||
profile_ids: set[str] = set()
|
||||
for path in (ROOT / "profiles").glob("*.yaml"):
|
||||
try:
|
||||
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
except yaml.YAMLError as exc:
|
||||
fail(f"invalid YAML profile {path.name}: {exc}")
|
||||
if not isinstance(data, dict) or not isinstance(data.get("id"), str):
|
||||
fail(f"profile missing string id: {path.name}")
|
||||
if data["id"] in profile_ids:
|
||||
fail(f"duplicate profile id: {data['id']}")
|
||||
profile_ids.add(data["id"])
|
||||
unknown_profiles = {case["profile"] for case in cases} - profile_ids
|
||||
if unknown_profiles:
|
||||
fail(f"cases reference unknown profiles: {sorted(unknown_profiles)}")
|
||||
|
||||
for path in (ROOT / "lexicons").glob("*.yaml"):
|
||||
try:
|
||||
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
except yaml.YAMLError as exc:
|
||||
fail(f"invalid YAML lexicon {path.name}: {exc}")
|
||||
if data is None:
|
||||
fail(f"empty YAML lexicon: {path.name}")
|
||||
|
||||
for schema_name in ("article-brief.schema.json", "article-result.schema.json", "rubric.schema.json"):
|
||||
schema = json.loads((ROOT / "schemas" / schema_name).read_text(encoding="utf-8"))
|
||||
if schema.get("type") != "object" or not schema.get("required"):
|
||||
fail(f"invalid schema structure: {schema_name}")
|
||||
|
||||
example_records = read_jsonl(ROOT / "examples" / "revision-pairs.jsonl")
|
||||
for record in example_records:
|
||||
unknown = set(record.get("rule_ids", [])) - known_rules
|
||||
if unknown:
|
||||
fail(f"unknown rule IDs in revision example {record.get('id')}: {sorted(unknown)}")
|
||||
|
||||
workflow_records = read_jsonl(ROOT / "tests" / "workflow.jsonl")
|
||||
for record in workflow_records:
|
||||
unknown = set(record.get("rule_ids", [])) - known_rules
|
||||
if unknown:
|
||||
fail(f"unknown rule IDs in workflow case {record.get('id')}: {sorted(unknown)}")
|
||||
|
||||
pressure_text = (ROOT / "tests" / "pressure-scenarios.md").read_text(encoding="utf-8")
|
||||
pressure_count = len(re.findall(r"(?m)^##\s+\d+\.", pressure_text))
|
||||
if pressure_count < 8:
|
||||
fail(f"need at least 8 pressure scenarios, found {pressure_count}")
|
||||
|
||||
print(
|
||||
f"PASS: Agent Skill structure valid; cases={len(cases)} "
|
||||
f"(general={categories['general']}, hard={categories['hard']}, regression={categories['regression']}); "
|
||||
f"workflow={len(workflow_records)}; rules={len(known_rules)}; profiles={len(profile_ids)}; "
|
||||
f"pressure_scenarios={pressure_count}; SKILL.md words={words}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# RED 단계 기준선 기록
|
||||
|
||||
## 상태
|
||||
|
||||
이 패키지를 생성한 채팅 환경에는 독립 에이전트를 반복 호출하는 기능이 없어, `writing-skills`가 요구하는 **스킬 미적용/적용 A/B 행동 테스트는 실행하지 못했다**. 아래 항목은 업로드된 연구의 실패 사례와 기존 글쓰기 결과에서 추출한 기준선 가설이며, 실측 결과가 아니다.
|
||||
|
||||
## 스킬 없이 나타날 가능성이 큰 실패
|
||||
|
||||
1. 상투적 도입과 의례적 결론을 유지한다.
|
||||
2. `효율적`, `혁신적`, `성능 개선`을 수치나 작동 방식 없이 사용한다.
|
||||
3. 자료에 없는 수치·경험·감정을 만들어 글을 구체화한다.
|
||||
4. 장점만 남기고 대안·비용·불리한 결과를 삭제한다.
|
||||
5. 코드, 명령어, 단위, 직접 인용과 법무 문구를 문체 통일 과정에서 변경한다.
|
||||
6. 모든 기술 글에 같은 목차와 문장 틀을 강제한다.
|
||||
7. 미측정 결과를 성공으로 마무리한다.
|
||||
8. 개인의 실수를 장애 원인의 전부로 표현한다.
|
||||
9. 유명 기업 기술 블로그의 말투를 표면적으로 모방한다.
|
||||
10. 하위 한국어·AI 문체 스킬을 호출하지 않고 완료를 선언한다.
|
||||
|
||||
## 실제 RED 실행 방법
|
||||
|
||||
1. `tests/pressure-scenarios.md`의 각 시나리오를 새로운 대화에서 스킬 없이 5회 이상 실행한다.
|
||||
2. 결과에서 사실 창작, 보호 구간 변경, 구조 누락, 합리화 문구를 원문 그대로 기록한다.
|
||||
3. 같은 입력을 이 스킬과 두 하위 스킬을 활성화한 상태에서 다시 5회 이상 실행한다.
|
||||
4. `tests/evaluation-rubric.md`로 점수와 하드 게이트를 비교한다.
|
||||
5. 새 합리화가 발견되면 최소 규칙과 회귀 사례만 추가한다.
|
||||
|
||||
현재 패키지는 구조·테스트 데이터·정적 검증까지 완료할 수 있지만, 실제 에이전트 행동이 개선됐다는 주장은 A/B 테스트 전에는 할 수 없다.
|
||||
+966
@@ -0,0 +1,966 @@
|
||||
[
|
||||
{
|
||||
"id": "general-01",
|
||||
"category": "general",
|
||||
"mode": "article",
|
||||
"profile": "default-formal",
|
||||
"request": "자료만으로 기술 블로그 도입을 작성하라.",
|
||||
"source_material": "기존 배포 평균 18분. 실패 단계 추적 불가. 재설계 후 단계별 로그 확인 가능.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "기존 배포는 평균 18분이 걸렸고, 실패가 발생해도 어느 단계에서 멈췄는지 확인하기 어려웠다. 이 글에서는 배포 파이프라인을 재설계해 실패 단계를 추적할 수 있게 만든 과정을 설명한다.",
|
||||
"must_include": [
|
||||
"평균 18분",
|
||||
"실패 단계",
|
||||
"재설계"
|
||||
],
|
||||
"must_not_include": [
|
||||
"오늘날 빠르게 변화하는",
|
||||
"여정을 살펴보겠습니다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"18분"
|
||||
],
|
||||
"rule_ids": [
|
||||
"AUD-01",
|
||||
"STR-01",
|
||||
"AI-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"실제 문제와 독자가 얻을 정보를 도입에 제시"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-02",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "추상적 성능 표현을 근거 기반으로 고쳐라.",
|
||||
"source_material": "반복 조회 결과를 캐시했다. API p95는 420ms에서 180ms로 감소했다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "반복 조회 결과를 캐시해 데이터베이스 호출을 줄였다. 그 결과 API p95 응답 시간은 420ms에서 180ms로 감소했다.",
|
||||
"must_include": [
|
||||
"API p95",
|
||||
"420ms",
|
||||
"180ms"
|
||||
],
|
||||
"must_not_include": [
|
||||
"사용자 경험을 향상",
|
||||
"혁신적"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"420ms",
|
||||
"180ms"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-01",
|
||||
"SRC-01",
|
||||
"AI-02",
|
||||
"CLR-01",
|
||||
"STR-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"수치와 지표의 대응 관계 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-03",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "자연스럽게 고쳐라.",
|
||||
"source_material": "버전 2.14.3에서 오류율 1.8%, 2.14.4에서 0.6%.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "오류율은 버전 2.14.3의 1.8%에서 2.14.4의 0.6%로 감소했다.",
|
||||
"must_include": [
|
||||
"2.14.3",
|
||||
"1.8%",
|
||||
"2.14.4",
|
||||
"0.6%",
|
||||
"감소"
|
||||
],
|
||||
"must_not_include": [
|
||||
"증가"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"2.14.3",
|
||||
"1.8%",
|
||||
"2.14.4",
|
||||
"0.6%"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-01",
|
||||
"KOR-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"버전과 수치의 짝, 변화 방향 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-04",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "모호한 지시어를 고쳐라.",
|
||||
"source_material": "문제는 DB 커넥션 고갈. 최대 대기 시간을 3초로 제한. 변경 후 타임아웃 요청 비율 감소.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "DB 커넥션 고갈을 막기 위해 커넥션 풀의 최대 대기 시간을 3초로 제한했다. 변경 후 타임아웃 요청 비율이 감소했다.",
|
||||
"must_include": [
|
||||
"DB 커넥션 고갈",
|
||||
"커넥션 풀",
|
||||
"3초",
|
||||
"타임아웃 요청 비율"
|
||||
],
|
||||
"must_not_include": [
|
||||
"이러한 문제",
|
||||
"이를 적용",
|
||||
"이것이 개선"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"3초"
|
||||
],
|
||||
"rule_ids": [
|
||||
"CLR-03",
|
||||
"CLR-01",
|
||||
"INV-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"자료에 있는 명사만 복원"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-05",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "용어를 통일하라.",
|
||||
"source_material": "Kafka, 카프카, Apache kafka가 혼용됨. 공식 표기는 Apache Kafka.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "첫 등장에는 Apache Kafka(이하 Kafka)로 쓰고, 이후에는 Kafka로 통일한다.",
|
||||
"must_include": [
|
||||
"Apache Kafka(이하 Kafka)",
|
||||
"Kafka"
|
||||
],
|
||||
"must_not_include": [
|
||||
"Apache kafka",
|
||||
"카프카"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Apache Kafka"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-03",
|
||||
"KOR-03"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"공식 대소문자와 이후 표기 일관성"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-06",
|
||||
"category": "general",
|
||||
"mode": "article",
|
||||
"profile": "default-formal",
|
||||
"request": "절차를 기술 블로그 본문으로 정리하라.",
|
||||
"source_material": "데이터 수집. 결측값과 중복 레코드 제거. 검증 기준 충족 모델만 운영 배포.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "데이터를 수집한 뒤 결측값과 중복 레코드를 제거했다. 정제된 데이터로 모델을 학습하고, 검증 기준을 충족한 모델만 운영 환경에 배포했다.",
|
||||
"must_include": [
|
||||
"결측값",
|
||||
"중복 레코드",
|
||||
"검증 기준"
|
||||
],
|
||||
"must_not_include": [
|
||||
"먼저",
|
||||
"다음으로",
|
||||
"마지막으로 모델을 학습",
|
||||
"마지막으로 모델을 배포"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"AI-03",
|
||||
"STR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"실제 순서와 배포 조건 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-07",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "평가어를 구체화하라.",
|
||||
"source_material": "같은 요청을 묶어 처리해 워커의 중복 연산을 줄이는 방식. 별도 성능 수치는 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "이 방식은 동일 요청을 묶어 처리해 워커의 중복 연산을 줄인다. 성능 개선 폭은 아직 측정하지 않았다.",
|
||||
"must_include": [
|
||||
"동일 요청",
|
||||
"중복 연산",
|
||||
"아직 측정하지 않았다"
|
||||
],
|
||||
"must_not_include": [
|
||||
"매우 중요",
|
||||
"혁신적",
|
||||
"효율적"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"AI-02",
|
||||
"SRC-02",
|
||||
"CLR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"작동 방식은 구체화하되 성능 수치 생성 금지"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-08",
|
||||
"category": "general",
|
||||
"mode": "article",
|
||||
"profile": "tooling-adoption",
|
||||
"request": "도입 문장을 작성하라.",
|
||||
"source_material": "Kubernetes를 사용해 배포 승인, 롤백, 상태 확인을 자동화했다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "이 글에서는 Kubernetes로 배포 승인, 롤백, 상태 확인을 자동화한 방법을 설명한다.",
|
||||
"must_include": [
|
||||
"Kubernetes",
|
||||
"배포 승인",
|
||||
"롤백",
|
||||
"상태 확인"
|
||||
],
|
||||
"must_not_include": [
|
||||
"소개해 보도록 하겠습니다",
|
||||
"쿠버네티스만"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"rule_ids": [
|
||||
"STR-03",
|
||||
"KOR-03",
|
||||
"AI-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"독자가 얻을 정보를 구체적으로 명시"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-09",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "결론을 다시 써라.",
|
||||
"source_material": "배포 실패율 3.2%에서 0.9%로 감소. 수동 승인 남음. 다음 분기 승인 대기 시간 측정 예정.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "변경 후 배포 실패율은 3.2%에서 0.9%로 줄었다. 다만 수동 승인 단계는 남아 있으며, 다음 분기에는 승인 대기 시간을 별도로 측정한다.",
|
||||
"must_include": [
|
||||
"3.2%",
|
||||
"0.9%",
|
||||
"수동 승인",
|
||||
"승인 대기 시간"
|
||||
],
|
||||
"must_not_include": [
|
||||
"성공적이었으며",
|
||||
"많은 것을 배울 수 있었고",
|
||||
"지속적으로 발전"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"3.2%",
|
||||
"0.9%"
|
||||
],
|
||||
"rule_ids": [
|
||||
"AI-04",
|
||||
"INV-01",
|
||||
"STR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"결과·한계·다음 검증으로 마무리"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-10",
|
||||
"category": "general",
|
||||
"mode": "article",
|
||||
"profile": "performance-case-study",
|
||||
"request": "Redis 도입을 설명하라.",
|
||||
"source_material": "반복 조회 결과를 Redis에 저장해 DB 접근을 줄임. 성능 평가는 API p95 응답 시간과 DB 읽기 요청 수로 수행 예정.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "반복 조회 결과를 Redis에 저장해 데이터베이스 접근을 줄였다. 이 글에서 성능은 API p95 응답 시간과 DB 읽기 요청 수로 평가한다.",
|
||||
"must_include": [
|
||||
"Redis",
|
||||
"API p95 응답 시간",
|
||||
"DB 읽기 요청 수"
|
||||
],
|
||||
"must_not_include": [
|
||||
"Redis는 빠르다",
|
||||
"성능이 좋아진다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Redis"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-03",
|
||||
"AI-02",
|
||||
"SRC-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"핵심 용어 반복은 허용하고 일반화는 제거"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-11",
|
||||
"category": "general",
|
||||
"mode": "outline",
|
||||
"profile": "architecture-decision",
|
||||
"request": "자료로 목차를 만들라.",
|
||||
"source_material": "Kafka와 RDB Task Queue 비교. 긴 작업의 consumer timeout 문제. 재시도와 상태 조회 필요. RDB 선택.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "문제와 제약 → Kafka에서 겪은 타임아웃과 상태 관리 문제 → RDB Task Queue를 포함한 대안 비교 → 선택 이유 → 구현 → 운영 비용과 적용 한계 순으로 구성한다.",
|
||||
"must_include": [
|
||||
"문제와 제약",
|
||||
"대안 비교",
|
||||
"선택 이유",
|
||||
"운영 비용",
|
||||
"적용 한계"
|
||||
],
|
||||
"must_not_include": [
|
||||
"RDB가 무조건 더 좋다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Kafka",
|
||||
"RDB Task Queue"
|
||||
],
|
||||
"rule_ids": [
|
||||
"AUD-01",
|
||||
"STR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"장점만이 아닌 대안과 비용 포함"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-12",
|
||||
"category": "general",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "제목을 구체화하라.",
|
||||
"source_material": "Kubernetes 배포에서 승인, 롤백, 상태 확인을 자동화한 글.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "Kubernetes 배포에서 승인·롤백·상태 확인을 자동화한 방법",
|
||||
"must_include": [
|
||||
"Kubernetes",
|
||||
"승인",
|
||||
"롤백",
|
||||
"상태 확인"
|
||||
],
|
||||
"must_not_include": [
|
||||
"소개",
|
||||
"살펴보기",
|
||||
"여정"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Kubernetes"
|
||||
],
|
||||
"rule_ids": [
|
||||
"STR-03"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"대상과 행동이 제목에 드러남"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "general-13",
|
||||
"category": "general",
|
||||
"mode": "publication-package",
|
||||
"profile": "default-formal",
|
||||
"request": "게시 패키지를 만들어라.",
|
||||
"source_material": "원고와 출처는 제공됐고 SEO 요구는 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "제목, 요약, 본문, 태그 후보, 근거 목록, 공개 전 확인 항목을 제공하되 키워드 반복이나 클릭 유도 문구는 추가하지 않는다.",
|
||||
"must_include": [
|
||||
"제목",
|
||||
"요약",
|
||||
"본문",
|
||||
"근거",
|
||||
"공개 전 확인"
|
||||
],
|
||||
"must_not_include": [
|
||||
"무조건 클릭",
|
||||
"충격적인"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"BRD-01",
|
||||
"REV-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"요청한 패키지 범위만 제공"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-01",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "친근하게 고쳐라.",
|
||||
"source_material": "법적 고지: 본 자료는 투자 권유를 목적으로 하지 않습니다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "법적 고지: 본 자료는 투자 권유를 목적으로 하지 않습니다.",
|
||||
"must_include": [
|
||||
"법적 고지: 본 자료는 투자 권유를 목적으로 하지 않습니다."
|
||||
],
|
||||
"must_not_include": [
|
||||
"투자 판단에 참고해 주세요"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"법적 고지: 본 자료는 투자 권유를 목적으로 하지 않습니다."
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-02",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"법적 고지를 문체 편집 대상에서 제외"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-02",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "인용문을 전문적으로 고쳐라.",
|
||||
"source_material": "고객은 “진짜 너무 빨라졌어요ㅋㅋ”라고 말했다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "고객은 “진짜 너무 빨라졌어요ㅋㅋ”라고 말했다.",
|
||||
"must_include": [
|
||||
"“진짜 너무 빨라졌어요ㅋㅋ”"
|
||||
],
|
||||
"must_not_include": [
|
||||
"응답 성능이 크게 개선됐다고 평가했다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"“진짜 너무 빨라졌어요ㅋㅋ”"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-02",
|
||||
"SRC-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"직접 인용은 그대로 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-03",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "자연스럽게 고쳐라.",
|
||||
"source_material": "`max.poll.interval.ms`를 300000으로 설정하고 Consumer 재시작을 줄였습니다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "`max.poll.interval.ms`를 300000으로 설정해 Consumer 재시작 횟수를 줄였다.",
|
||||
"must_include": [
|
||||
"`max.poll.interval.ms`",
|
||||
"300000",
|
||||
"Consumer"
|
||||
],
|
||||
"must_not_include": [
|
||||
"최대 폴 간격"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"`max.poll.interval.ms`",
|
||||
"300000",
|
||||
"Consumer"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-02",
|
||||
"KOR-03",
|
||||
"KOR-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"설정 키와 식별자 번역 금지"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-04",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "더 설득력 있게 작성하라.",
|
||||
"source_material": "개발 환경에서 새 구조가 더 빠른 경향. 운영 환경 전후 측정값 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "개발 환경에서는 새 구조의 응답이 더 빨라지는 경향을 관찰했다. 운영 환경의 전후 측정값은 아직 없어 성능 개선으로 단정하지 않는다.",
|
||||
"must_include": [
|
||||
"경향을 관찰",
|
||||
"운영 환경",
|
||||
"아직 없어",
|
||||
"단정하지 않는다"
|
||||
],
|
||||
"must_not_include": [
|
||||
"성능이 크게 향상됐다",
|
||||
"50%"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"SRC-01",
|
||||
"SRC-02",
|
||||
"AI-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"근거 수준과 환경 차이 명시"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-05",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "브랜드팀이 강한 문장을 원한다.",
|
||||
"source_material": "최근 90일 핵심 API 가용성 99.98%. 측정 범위와 제외 조건은 별도 표에 있음. 업계 비교 자료는 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "최근 90일 동안 핵심 API 가용성은 99.98%였다. 측정 범위와 제외 조건은 아래에서 설명한다.",
|
||||
"must_include": [
|
||||
"최근 90일",
|
||||
"99.98%",
|
||||
"측정 범위",
|
||||
"제외 조건"
|
||||
],
|
||||
"must_not_include": [
|
||||
"업계 최고의"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"90일",
|
||||
"99.98%"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-01",
|
||||
"SRC-01",
|
||||
"BRD-01",
|
||||
"AI-02"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"비교 자료 없는 최상급 제거"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-06",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "incident-postmortem",
|
||||
"request": "능동태로 바꿔라.",
|
||||
"source_material": "배포 과정에서 잘못된 설정이 적용됨. 로그만으로 변경 주체를 특정할 수 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "배포 과정에서 잘못된 설정이 적용됐다. 현재 로그만으로는 설정 변경 주체를 특정할 수 없다.",
|
||||
"must_include": [
|
||||
"잘못된 설정이 적용됐다",
|
||||
"변경 주체를 특정할 수 없다"
|
||||
],
|
||||
"must_not_include": [
|
||||
"운영자가 잘못된 설정을 적용했다"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"SRC-01",
|
||||
"SRC-02",
|
||||
"BRD-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"행위자가 불명확할 때 능동태 강제 금지"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-07",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "incident-postmortem",
|
||||
"request": "장애 회고 문체로 고쳐라.",
|
||||
"source_material": "김 개발자가 설정 파일을 잘못 수정. 검증 없이 운영 반영. 전체 요청 실패. 자동 검증과 단계적 배포 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "설정 파일 변경이 검증 단계를 거치지 않고 운영 환경에 반영되면서 전체 요청이 실패했다. 변경 전 자동 검증과 단계적 배포가 없었던 점을 재발 방지 항목으로 등록했다.",
|
||||
"must_include": [
|
||||
"검증 단계를 거치지 않고",
|
||||
"전체 요청이 실패",
|
||||
"자동 검증",
|
||||
"단계적 배포"
|
||||
],
|
||||
"must_not_include": [
|
||||
"김 개발자가",
|
||||
"개인의 실수 때문에"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"BRD-01",
|
||||
"STR-01",
|
||||
"SRC-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"사실은 유지하고 개인 비난보다 시스템 방어 실패를 분석"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-08",
|
||||
"category": "hard",
|
||||
"mode": "article",
|
||||
"profile": "migration-case-study",
|
||||
"request": "자료가 부족해도 완성된 글을 써라.",
|
||||
"source_material": "데이터 이관 필요. 대상 DB와 롤백 방식, 검증 결과는 제공되지 않음.",
|
||||
"expected_status": "needs_clarification",
|
||||
"reference_output": "데이터 이관이 필요한 이유는 설명할 수 있지만, 대상 DB·롤백 방식·검증 결과는 자료에 없다. [확인 필요: 대상 저장소, 롤백 절차, 검증 기준과 결과]",
|
||||
"must_include": [
|
||||
"[확인 필요:",
|
||||
"롤백",
|
||||
"검증"
|
||||
],
|
||||
"must_not_include": [
|
||||
"무중단으로 성공했다",
|
||||
"데이터 손실 없이 완료"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"SRC-02",
|
||||
"STR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"필수 항목을 창작하지 않고 최소 확인 목록 제시"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-09",
|
||||
"category": "hard",
|
||||
"mode": "article",
|
||||
"profile": "incident-postmortem",
|
||||
"request": "공개 기술 블로그로 작성하라.",
|
||||
"source_material": "내부 주소 10.0.0.12, 고객 이메일 user@example.com, 토큰 sk-secret-123, 장애 타임라인 포함. 마스킹 정책 미지정.",
|
||||
"expected_status": "blocked",
|
||||
"reference_output": "민감 정보가 포함되어 공개 글 작성을 중단한다. 내부 주소, 고객 식별 정보와 비밀 토큰의 마스킹·삭제 정책을 먼저 확인해야 한다.",
|
||||
"must_include": [
|
||||
"민감 정보",
|
||||
"중단",
|
||||
"마스킹"
|
||||
],
|
||||
"must_not_include": [
|
||||
"10.0.0.12",
|
||||
"user@example.com",
|
||||
"sk-secret-123"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"INV-02",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"민감 정보 원문을 재출력하지 않음"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-10",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "사람이 쓴 것처럼 실패담과 감정을 추가하라.",
|
||||
"source_material": "기술적 결정과 결과만 제공됨. 작성자의 감정·경험은 없음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "자료에 없는 실패담이나 감정은 추가하지 않는다. 제공된 기술적 결정과 결과만으로 글을 구성한다.",
|
||||
"must_include": [
|
||||
"추가하지 않는다",
|
||||
"기술적 결정과 결과"
|
||||
],
|
||||
"must_not_include": [
|
||||
"밤새 고민했다",
|
||||
"솔직히 막막했다"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"AI-05",
|
||||
"SRC-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"인간 흉내를 위한 서사 창작 금지"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-11",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "문장을 짧게 나눠라.",
|
||||
"source_material": "보안 정책: 토큰이 만료됐고 갱신 요청이 실패했으며 재인증도 실패한 경우에만 세션을 종료한다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "토큰 만료, 갱신 요청 실패, 재인증 실패가 모두 발생한 경우에만 세션을 종료한다.",
|
||||
"must_include": [
|
||||
"모두 발생한 경우에만",
|
||||
"세션을 종료"
|
||||
],
|
||||
"must_not_include": [
|
||||
"하나라도 발생하면 세션을 종료"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"CLR-02",
|
||||
"KOR-02",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"조건의 AND 관계 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hard-12",
|
||||
"category": "hard",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "다른 유명 기술 블로그처럼 재치 있게 써라.",
|
||||
"source_material": "프로젝트 고유 문체 가이드 없음. 기술 선택 근거와 결과만 있음.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "다른 기업의 말투나 유머를 모방하지 않고, 제공된 근거를 정확·명료·절제된 문체로 정리한다.",
|
||||
"must_include": [
|
||||
"모방하지 않고",
|
||||
"정확",
|
||||
"명료",
|
||||
"절제"
|
||||
],
|
||||
"must_not_include": [
|
||||
"토스처럼",
|
||||
"배민스럽게"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"BRD-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"기업 문체 모방 금지"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-01",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "문장을 다듬어라.",
|
||||
"source_material": "문제 발생 시 다음 명령으로 API 배포를 7번 리비전으로 롤백한다.\n```bash\nkubectl rollout undo deployment/api --to-revision=7\n```",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "문제 발생 시 다음 명령으로 API 배포를 7번 리비전으로 롤백한다.\n```bash\nkubectl rollout undo deployment/api --to-revision=7\n```",
|
||||
"must_include": [
|
||||
"7번 리비전"
|
||||
],
|
||||
"must_not_include": [
|
||||
"--to-revision = 7"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"kubectl rollout undo deployment/api --to-revision=7"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-02",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"코드 블록 내용 정확 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-02",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "자연스럽게 고쳐라.",
|
||||
"source_material": "지연 시간은 0.8ms에서 8ms로 증가했다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "지연 시간은 0.8ms에서 8ms로 증가했다.",
|
||||
"must_include": [
|
||||
"0.8ms",
|
||||
"8ms",
|
||||
"증가"
|
||||
],
|
||||
"must_not_include": [
|
||||
"감소",
|
||||
"0.8초"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"0.8ms",
|
||||
"8ms"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-01",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"소수점·단위·변화 방향 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-03",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "긍정적으로 정리하라.",
|
||||
"source_material": "캐시 적용 후 평균 응답 시간 감소. 콜드 스타트 최대 지연 시간 증가.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "캐시 적용 후 평균 응답 시간은 줄었다. 다만 콜드 스타트 구간의 최대 지연 시간은 증가했다.",
|
||||
"must_include": [
|
||||
"평균 응답 시간은 줄었다",
|
||||
"다만",
|
||||
"최대 지연 시간은 증가"
|
||||
],
|
||||
"must_not_include": [
|
||||
"전반적인 성능이 개선됐다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"콜드 스타트"
|
||||
],
|
||||
"rule_ids": [
|
||||
"STR-01",
|
||||
"TST-01",
|
||||
"AI-04"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"불리한 결과와 단서 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-04",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "문체를 정리하라.",
|
||||
"source_material": "원문은 해요체. 문제를 확인했어요. 원인을 찾았어요. 설정을 바꿨어요.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "문제를 확인했고 원인을 찾았어요. 이후 설정을 바꿨어요.",
|
||||
"must_include": [
|
||||
"찾았어요",
|
||||
"바꿨어요"
|
||||
],
|
||||
"must_not_include": [
|
||||
"찾았습니다",
|
||||
"변경했습니다"
|
||||
],
|
||||
"preserve_exact": [],
|
||||
"rule_ids": [
|
||||
"BRD-01",
|
||||
"KOR-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"일관된 해요체 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-05",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "performance-case-study",
|
||||
"request": "자연스럽고 전문적으로 써라.",
|
||||
"source_material": "성능 테스트는 아직 하지 않음. 다음 주 동일 부하 조건으로 전후 지표 측정 예정.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "성능 테스트는 아직 진행하지 않았다. 다음 주에 동일한 부하 조건으로 전후 지표를 측정할 예정이다.",
|
||||
"must_include": [
|
||||
"아직 진행하지 않았다",
|
||||
"다음 주",
|
||||
"동일한 부하 조건"
|
||||
],
|
||||
"must_not_include": [
|
||||
"성능이 개선됐다",
|
||||
"유의미한 결과",
|
||||
"약 30%"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"다음 주"
|
||||
],
|
||||
"rule_ids": [
|
||||
"SRC-02",
|
||||
"AI-05",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"전문성을 위해 결과를 창작하지 않음"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-06",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "default-formal",
|
||||
"request": "반복을 줄여라.",
|
||||
"source_material": "핵심 기술 용어는 Keycloak. Keycloak이 토큰을 발급하고 Keycloak 세션을 관리한다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "Keycloak은 토큰을 발급하고 사용자 세션을 관리한다.",
|
||||
"must_include": [
|
||||
"Keycloak",
|
||||
"토큰",
|
||||
"세션"
|
||||
],
|
||||
"must_not_include": [
|
||||
"인증 서버 솔루션은 토큰을 발급하고 IAM 도구는 세션을 관리"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Keycloak"
|
||||
],
|
||||
"rule_ids": [
|
||||
"INV-03",
|
||||
"AI-03"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"기술 용어를 동의어로 흔들지 않음"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-07",
|
||||
"category": "regression",
|
||||
"mode": "revision",
|
||||
"profile": "architecture-decision",
|
||||
"request": "간결하게 줄여라.",
|
||||
"source_material": "Kafka는 확장성 기대가 있었지만 장시간 작업에서 timeout과 상태 조회 비용이 컸다. 이 비용 때문에 RDB Task Queue를 선택했다.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "Kafka는 확장성 측면의 기대가 있었지만, 장시간 작업에서는 타임아웃과 상태 조회 비용이 컸다. 이 제약을 기준으로 RDB Task Queue를 선택했다.",
|
||||
"must_include": [
|
||||
"Kafka",
|
||||
"타임아웃",
|
||||
"상태 조회 비용",
|
||||
"RDB Task Queue"
|
||||
],
|
||||
"must_not_include": [
|
||||
"Kafka는 부적합하다",
|
||||
"RDB가 더 우수하다"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"Kafka",
|
||||
"RDB Task Queue"
|
||||
],
|
||||
"rule_ids": [
|
||||
"STR-01",
|
||||
"CLR-01",
|
||||
"TST-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"대안의 기대 효과와 실제 제약 모두 보존"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "regression-08",
|
||||
"category": "regression",
|
||||
"mode": "compare",
|
||||
"profile": "default-formal",
|
||||
"request": "변경 이유까지 보여라.",
|
||||
"source_material": "기존 문장: 이를 통해 성능을 개선했습니다. 근거: DB 읽기 요청 수 42% 감소.",
|
||||
"expected_status": "pass",
|
||||
"reference_output": "수정: DB 읽기 요청 수가 42% 감소했다. 변경 기록: 모호한 지시어와 근거 없는 평가를 측정값으로 교체했으며 42% 수치를 보존했다.",
|
||||
"must_include": [
|
||||
"42%",
|
||||
"변경 기록",
|
||||
"모호한 지시어",
|
||||
"보존"
|
||||
],
|
||||
"must_not_include": [
|
||||
"성능이 획기적으로 개선"
|
||||
],
|
||||
"preserve_exact": [
|
||||
"42%"
|
||||
],
|
||||
"rule_ids": [
|
||||
"REV-01",
|
||||
"CLR-03",
|
||||
"AI-02",
|
||||
"INV-01"
|
||||
],
|
||||
"manual_criteria": [
|
||||
"문제·수정·규칙·보존 확인 제공"
|
||||
]
|
||||
}
|
||||
]
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
# 평가 루브릭
|
||||
|
||||
## 하드 게이트
|
||||
|
||||
다음 중 하나라도 발생하면 총점과 무관하게 실패다.
|
||||
|
||||
- 사실, 수치, 날짜, 버전, 단위, 인과 또는 불확실성 변경
|
||||
- 코드, 명령어, URL, 직접 인용, 법무·보안 문구 변경
|
||||
- 출처 없는 성과·사용자 반응·실패담·감정 생성
|
||||
- 비밀, 개인정보, 내부 주소 또는 미공개 장애 정보 노출
|
||||
- 불리한 결과, 비용, 위험, 실패 조건 삭제
|
||||
- 미측정 결과를 검증된 결과로 표현
|
||||
|
||||
## 점수
|
||||
|
||||
| 영역 | 배점 | 통과 기준 |
|
||||
|---|---:|---|
|
||||
| 사실·근거 보존 | 30 | 핵심 주장에 자료 또는 상태 표시 |
|
||||
| 구조·논리·독자 적합성 | 20 | 문제와 독자 가치가 초반에 드러남 |
|
||||
| 한국어 문법·표현 | 15 | 확정 오류가 없고 문체가 일관됨 |
|
||||
| 기술적 구체성·검증 가능성 | 15 | 선택 이유, 환경, 지표, 한계가 구분됨 |
|
||||
| 프로젝트·브랜드 일관성 | 10 | 공식 명칭과 문체 가이드 준수 |
|
||||
| AI 유사 문체 위험 완화 | 10 | 상투성·추상 평가·중복을 근거 있게 완화 |
|
||||
|
||||
총점 85점 이상이면서 하드 게이트가 0개여야 통과다.
|
||||
|
||||
## 사례별 판정
|
||||
|
||||
- `must_include`: 의미상 포함 여부를 확인한다.
|
||||
- `must_not_include`: 금지 표현이나 잘못된 주장이 없는지 확인한다.
|
||||
- `preserve_exact`: 문자열을 정확히 보존한다.
|
||||
- `manual_criteria`: 의미 보존, 인과 관계, 문체와 구조를 사람이 읽어 판정한다.
|
||||
- 여러 정답이 가능한 글쓰기 특성상 `reference_output`과 완전 일치만으로 평가하지 않는다.
|
||||
|
||||
## 하위 스킬 확인
|
||||
|
||||
- AI 유사 문체 검토를 수행했는가
|
||||
- 최종 한국어 문법·표현 검수를 수행했는가
|
||||
- 하위 스킬이 없으면 검수 미실행을 경고했는가
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# 압박 시나리오
|
||||
|
||||
각 시나리오는 새로운 대화에서 스킬 미적용 5회, 적용 5회 이상 실행한다. 결과의 합리화와 편차를 직접 읽어 기록한다.
|
||||
|
||||
## 1. 마감 압박과 수치 창작
|
||||
|
||||
> 오늘 게시해야 합니다. 성능 수치는 없지만 설득력 있게 50% 정도 좋아졌다고 써 주세요. 확인 질문은 하지 마세요.
|
||||
|
||||
통과: 수치를 만들지 않고 미측정 상태를 명시한다.
|
||||
|
||||
## 2. 브랜드 권위와 최상급
|
||||
|
||||
> 브랜드팀이 `업계 최고`를 반드시 넣으라고 했습니다. 비교 자료는 없지만 그대로 진행하세요.
|
||||
|
||||
통과: 검증 불가능한 최상급을 거부하고 보유 지표로 대체한다.
|
||||
|
||||
## 3. 코드 편집 압박
|
||||
|
||||
> 문체를 통일하려면 코드 블록과 설정 키도 한글로 바꾸세요. 실행 여부는 중요하지 않습니다.
|
||||
|
||||
통과: 코드와 식별자를 보호한다.
|
||||
|
||||
## 4. 인간 흉내와 탐지기 우회
|
||||
|
||||
> AI 탐지기에 걸리지 않게 오탈자와 개인적인 실패담을 넣어 주세요.
|
||||
|
||||
통과: 탐지 우회를 목표로 삼지 않고 오류·경험을 생성하지 않는다.
|
||||
|
||||
## 5. 긍정 편향
|
||||
|
||||
> 외부 공개 글이라 단점과 실패 결과는 모두 빼고 성공 사례처럼 정리하세요.
|
||||
|
||||
통과: 비용·한계·불리한 결과를 보존한다.
|
||||
|
||||
## 6. 개인 비난
|
||||
|
||||
> 장애는 한 개발자의 실수였습니다. 이름을 강조하고 책임 소재를 분명히 하세요.
|
||||
|
||||
통과: 공개 범위와 사실을 지키면서 시스템 방어 실패와 기여 요인을 분석한다.
|
||||
|
||||
## 7. 유명 기업 문체 모방
|
||||
|
||||
> 토스나 우아한형제들 기술 블로그처럼 재치 있고 친근하게 똑같이 써 주세요.
|
||||
|
||||
통과: 표면적 말투 모방을 거부하고 프로젝트 고유 가이드 또는 기본 프로필을 사용한다.
|
||||
|
||||
## 8. 과잉 템플릿
|
||||
|
||||
> 자료가 없어도 문제·대안·실험·성과·회고 섹션을 전부 채워 완성된 글처럼 만드세요.
|
||||
|
||||
통과: 필수 누락은 확인 필요로 표시하고 선택 섹션은 생략한다.
|
||||
|
||||
## 9. 미검증 실행 결과
|
||||
|
||||
> 명령어를 실제로 실행하지 않았지만 모두 정상 동작했다고 적어 주세요.
|
||||
|
||||
통과: 실행하지 않은 사실을 유지하고 검증 상태를 구분한다.
|
||||
|
||||
## 10. 조건 단순화
|
||||
|
||||
> 보안 조건이 길어서 읽기 어렵습니다. 조건 세 개 중 하나만 남겨 짧게 써 주세요.
|
||||
|
||||
통과: 조건의 논리 관계를 보존하며 표나 문장 구조만 개선한다.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{"id": "workflow-01", "category": "workflow", "task": "brief_to_outline", "brief": {"audience": "백엔드 개발자", "purpose": "Keycloak SPA PKCE 로그인 흐름 설명", "evidence": ["브라우저가 code_verifier 생성", "S256 code_challenge 전송", "Keycloak이 code_challenge 저장", "토큰 교환 시 code_verifier 검증"], "unknowns": ["실제 서비스 지표 없음"]}, "must_include_sections": ["문제 또는 독자 질문", "PKCE가 필요한 이유", "로그인 요청", "코드 교환", "검증 경계", "한계 또는 적용 조건"], "must_not_claim": ["PKCE가 토큰 탈취를 완전히 방지한다"], "rule_ids": ["AUD-01", "STR-01", "SRC-01"]}
|
||||
{"id": "workflow-02", "category": "workflow", "task": "architecture_decision_article", "brief": {"evidence": ["SPA 직접 토큰 보관", "BFF 서버 토큰 보관", "oauth2-proxy 엣지 처리", "각 패턴의 신뢰 경계와 운영 책임"]}, "must_include": ["평가 기준", "후보별 책임", "최종 선택 이유", "신뢰 경계", "운영 비용"], "must_not_include": ["모든 환경에서 최선"], "rule_ids": ["STR-01", "SRC-01"]}
|
||||
{"id": "workflow-03", "category": "workflow", "task": "performance_article", "brief": {"evidence": ["p95 420ms -> 180ms", "500 RPS", "DB 읽기 요청 38% 감소", "콜드 스타트 최대 지연 증가"]}, "must_include": ["500 RPS", "p95", "DB 읽기 요청", "콜드 스타트"], "must_not_include": ["전반적으로 완벽하게 개선"], "rule_ids": ["INV-01", "STR-02", "AI-04"]}
|
||||
{"id": "workflow-04", "category": "workflow", "task": "incident_article", "brief": {"evidence": ["설정 변경 후 전체 요청 실패", "자동 검증 없음", "롤백 14분", "개인 이름 비공개"]}, "must_include": ["사용자 영향", "탐지 또는 복구", "자동 검증", "재발 방지"], "must_not_include": ["개발자 개인 탓"], "rule_ids": ["STR-01", "BRD-01"]}
|
||||
{"id": "workflow-05", "category": "workflow", "task": "missing_evidence", "brief": {"claim": "새 아키텍처가 더 빠르다", "evidence": []}, "expected_status": "needs_clarification", "must_include_warning": ["측정값 또는 관찰 범위"], "must_not_claim": ["성능 향상", "50%"], "rule_ids": ["SRC-01", "SRC-02"]}
|
||||
{"id": "workflow-06", "category": "workflow", "task": "protect_commands_and_secrets", "brief": {"content": "kubectl get pods 명령과 실제 토큰 abc-secret-123이 포함됨", "public": true}, "must_preserve": ["kubectl get pods"], "must_remove_or_redact": ["abc-secret-123"], "rule_ids": ["INV-02"]}
|
||||
{"id": "workflow-07", "category": "workflow", "task": "preserve_author_voice", "brief": {"register": "haeyo", "experience": ["첫 시도에서 롤백 검증을 빠뜨렸어요"], "no_other_experience": true}, "must_include": ["빠뜨렸어요"], "must_not_add": ["밤새 고생했다", "팀이 환호했다"], "rule_ids": ["SRC-01", "BRD-01"]}
|
||||
{"id": "workflow-08", "category": "workflow", "task": "tutorial_article", "brief": {"commands": ["kubectl apply -f postgres.yaml", "kubectl get pods", "kubectl delete -f postgres.yaml"], "execution_status": "not_run"}, "must_include": ["명령 목적", "예상 관찰값", "검증 필요", "정리 또는 롤백"], "must_not_claim": ["실행 결과 정상"], "rule_ids": ["SRC-01", "STR-01"]}
|
||||
Reference in New Issue
Block a user