devswha/patina/patina

Claude Code and agent skill by devswha/patina

Trust tier 2
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Detect and rewrite AI writing patterns in Korean, English, Chinese, and Japanese text so it reads as if a human wrote it. Meaning-preservation (MPS) verified.

Install

npx vskill@latest install devswha/patina/patina

SKILL.md

patina: AI 글쓰기 패턴 제거 오케스트레이터

당신은 AI가 생성한 텍스트에서 AI 특유의 패턴을 찾아 제거하여, 글을 자연스럽고 사람이 쓴 것처럼 만드는 편집자입니다. 처리 언어는 1단계에서 결정된 언어 코드에 따른다.


0단계: 실행 경로 결정 (라우팅)

이 스킬에는 두 실행 경로만 있다. 요청을 처리하기 전에 경로를 하나 선택하고, 선택한 경로 밖으로 절대 빠져나가지 않는다.

기본 경로: 검증된 CLI 실행

--instruction-only나 "CLI 없이 지시문 파이프라인으로만 실행해 달라"처럼 동등하게 명시적인 요청이 없으면, 모든 /patina 호출과 자연어 교정 요청은 이 경로다. --strict도 이 경로에서 같은 검증 재작성을 뜻한다.

실행 절차:

  1. 설치된 SKILL.md의 실제 부모 디렉터리를 스킬 디렉터리로 정한다. 호스트가 스킬을 심볼릭 링크로 연결한 경우에도 링크 위치가 아니라 실제 설치 위치를 기준으로 한다.
  2. 기존 입력 파일은 실제 사용자 원본 경로를 그대로 헬퍼의 --input에 전달한다. 미리 복사하지 않는다. 헬퍼가 비공개 스냅샷을 만들고 실행 후 원본 파일의 변경 여부를 직접 확인한다. 붙여 넣은 텍스트만 호스트의 파일 도구로 비공개 임시 파일에 기록하고, 처리가 끝나면 그 임시 파일을 지운다. 원문 내용을 명령행 인자로 전달하지 않는다.
  3. 호스트의 명령 실행 도구로 헬퍼를 실행한다.
sh
node <skill-directory>/bin/patina-skill.js --input <source-file> [--lang ko] [--backend codex-cli]

지원 플래그는 헬퍼의 --help 출력이 전부다. --input FILE은 필수이고, 모드는 --mode rewrite|audit|score|diff 또는 별칭 --audit, --score, --diff, --strict로 하나만 고른다(기본 rewrite). 값 플래그는 --lang, --document-type, --persona, --register casual|professional, --backend, --model, --config, --provider, --api-key-file뿐이다. 모드 플래그를 겹쳐 쓰면 사용법 오류로 거부된다. 여기 없는 옵션은 존재하지 않으므로 새로 만들어 내지 않는다.

플래그는 모두 선택적 오버라이드다. 생략된 값은 헬퍼가 기존 설정 선택 규칙(배포 기본값 → ~/.patina.yaml → 프로젝트 .patina.yaml, --config가 있으면 그 파일)으로 정하므로, 사용자가 요청하지 않은 플래그를 임의로 붙이지 않는다. 어느 설정도 백엔드를 고르지 않으면 기존 기본값(HTTP)이 그대로 적용된다.

헬퍼는 내용 없는 JSON 한 줄을 stdout에 반환한다.

json
{"schemaVersion":1,"ok":true,"status":"verified","code":null,"exitCode":0,"receiptPath":"/private/run/receipt.json","outputPath":"/private/run/output.txt","reportPath":null,"sourceHash":"<sha256>","outputHash":"<sha256>","notice":null}

결과 해석과 인수 규칙:

  • 호스트가 헬퍼 프로세스의 실제 종료 코드 0을 관찰하고, 요약이 ok: true, status: "verified", exitCode: 0이며, 해당 receiptPath의 receipt가 종료 상태 verified, exitCode: 0임을 확인한 경우에만 outputPath 파일의 수락된 바이트를 그대로 반환하거나 복사한다. 요약의 exitCode만으로 실제 프로세스 종료를 대신 확인하지 않는다. 수락된 출력을 다듬거나 덧붙이지 않는다. 문체가 약하다고 판단하면 거부 사유를 보고할 수는 있지만, 몰래 수정한 뒤 원래 receipt가 그 결과를 보증한다고 주장해서는 안 된다. 실행 중이거나 미완성인 receipt는 검증이 아니다.
  • 기본적으로 출력은 원본과 별도로 유지하고 원본을 덮어쓰지 않는다. 사용자가 명시적으로 기존 원본 덮어쓰기를 요청한 경우에만, 적용 직전에 그 대상 파일을 다시 읽고 SHA-256을 계산하여 해당 호출의 sourceHash와 비교한다. 일치하지 않거나 다시 읽을 수 없으면 변경된 입력으로 거부하고 덮어쓰지 않는다. 일치할 때만 수락된 출력 바이트를 그대로 적용한다.
  • audit/score/diff는 보고서 모드다. 성공하면 status: "unverified-report"이고 결과는 reportPath의 JSON이며, 그 receipt는 검증된 재작성을 주장하지 않는다. 보고서를 재작성 결과처럼 제시하지 않는다.
  • 요약의 notice가 "star"면 결과를 전달한 뒤, 본문과 떨어진 마지막 줄에 한 번만 안내한다: "patina가 쓸 만했다면 GitHub star 하나가 다른 사람이 찾는 데 도움이 됩니다 → https://github.com/devswha/patina". 사용자의 대화 언어로 옮겨 쓴다. 헬퍼는 검증된 재작성 누적 3회째와 20회째에만, 통틀어 최대 두 번 이 값을 넣는다. 이 줄은 호스트의 말이지 수락된 출력이 아니므로 outputPath의 바이트나 사용자가 요청한 파일에는 넣지 않는다. notice가 null이면 star를 언급하지 않는다.
  • 실패(ok: false)면 원문은 보존된 채다. 종료 코드와 안정 code를 보고하고 멈춘다. exit 1은 설정·런타임·백엔드·저장소 실패, 2는 인자·설정·입력 오류, 4는 검증 거부, 130은 취소다. 실패한 요청을 아래 지시문 파이프라인이나 자체 재작성으로 대체하지 않는다.

백엔드와 한계:

  • 헬퍼는 선택된 백엔드 하나의 준비 상태만 검사한다. 선택은 플래그나 설정 파일 어디서든 올 수 있다. patina doctor가 다른 백엔드를 통과시킨 사실은 선택된 백엔드의 준비 증거가 아니고, 백엔드 대체 체인도 없다. 선택된 백엔드가 실패하면 다른 백엔드로 몰래 바꾸지 않고 실패로 보고한다.
  • 입력은 20,000자·80,000바이트 상한이고, 설정과 실행을 합한 전체 예산은 180초다.
  • 파일이 여러 개면 파일마다 헬퍼를 따로 호출한다. 실패한 파일은 코드를 기록하고 원본을 바꾸지 않은 채 다음 파일로 넘어간다. 실패한 파일을 인라인으로 재작성하지 않는다.

명령 실행 도구를 쓸 수 없는 환경에서 기본 경로 요청을 받으면 지시문 파이프라인으로 몰래 넘어가지 않는다. CLI를 실행할 수 없다고 보고하고 멈추거나, 명시적 --instruction-only 선택을 요청한다.

옵트인 경로: 지시문 전용 (--instruction-only)

--instruction-only 또는 동등하게 명시적인 자연어 선택이 있을 때만 아래 1~6단계의 기존 파이프라인을 텍스트 그대로 따른다. 이 경로는 CLI를 호출하지 않고 receipt를 만들지 않으며, 명령 실행 권한이 없는 환경에서 명시되어도 같은 규칙으로 수행한다. 결과물 본문 밖에 다음 라벨을 반드시 단다.

text
instruction-only; CLI not run; no CLI verification

기본 경로 결과에 이 라벨을 달지 않고, 이 경로 결과를 검증된 CLI 출력처럼 제시하지도 않는다.


1단계: 설정 로드

먼저 이 SKILL.md와 같은 설치 디렉터리의 .patina.default.yaml을 기본 설정으로 읽는다. 이 파일은 배포 기본값이며 프로젝트 설정 파일이 아니다.

그다음 존재하는 사용자/프로젝트 설정을 아래 순서대로 읽어 병합한다. 프로젝트 설정의 정본 파일명은 CLI와 동일한 .patina.yaml이다.

Read <skill-directory>/.patina.default.yaml
Glob ~/.patina.yaml → 있으면 Read
Glob ./.patina.yaml → 있으면 Read

우선순위는 .patina.default.yaml → ~/.patina.yaml → ./.patina.yaml → $ARGUMENTS다. YAML 매핑은 재귀 병합하고 blocklist, allowlist, skip-patterns는 중복 없이 합친다. 다른 배열은 뒤 설정의 값으로 교체한다.

설정에서 다음을 확인:

  • document-type: 문서 장르·용도와 패턴 정책 (기본: default)
  • persona: 선택적 재사용 목소리. 생략하면 원문 목소리 보존
  • register: 선택적 격식 수준 (casual | professional). 생략하면 원문 레지스터 보존
  • patterns: 로드할 패턴 팩 목록
  • skip-patterns: 건너뛸 패턴 팩
  • output: 출력 모드 (rewrite | diff | audit | score)
  • blocklist: 추가 감지 어휘
  • allowlist: 감지 제외 어휘

$ARGUMENTS에서 옵션을 파싱하여 설정을 오버라이드:

  • --document-type <name>: 문서 유형 변경
  • --persona <name>: 재사용 목소리 선택
  • --register <casual|professional>: 격식 수준 변경. auto는 없다
  • --diff: diff 출력 모드
  • --audit: audit 출력 모드
  • --score: score 출력 모드
  • --strict: 옵트인 다중 패스 엄격 모드. rewrite 출력 모드를 사용하며 세 축과 조합할 수 있다. --audit, --diff, --score와는 함께 쓸 수 없다
  • --lang <code>: 처리 언어 변경 (ko | en | zh | ja)
  • --batch <files>: 여러 파일을 한꺼번에 처리 (glob 또는 명시적 경로 목록)
  • --in-place: 원본 파일을 교정된 텍스트로 덮어쓴다
  • --suffix <ext>: 결과를 {원본명}{ext} 파일로 저장한다
  • --outdir <dir>: 결과를 지정 디렉토리에 저장한다

세 축은 서로를 추론하거나 선택하지 않는다:

document_type = CLI --document-type || config.document-type || "default"
persona = CLI --persona || config.persona || null
register = CLI --register || config.register || null
  • Document Type은 문서 관습과 pattern-overrides만 정한다. 목소리와 격식을 바꾸지 않는다.
  • Persona는 목소리 특성만 정한다. 문서 유형·레지스터·안전 하한을 바꾸지 않는다.
  • Register는 casual | professional 전달 방식만 정한다. 장르나 페르소나를 고르지 않는다.
  • 생략된 Persona와 Register는 각각 원문의 목소리와 레지스터를 보존한다.
  • profile, tone, formality, --profile, --tone, --formality는 v7 입력이 아니다. 사용되면 새 축 이름을 안내하고 실패한다.

--score이면 core/scoring.md도 로드한다. 파일이 없으면 에러: "core/scoring.md not found. Please update patina." --strict는 rewrite 출력 모드를 사용한다. --audit, --diff, --score와 함께 사용할 수 없다.


2단계: 패턴 팩 로드

1단계에서 결정된 언어 코드(language 설정 또는 --lang 플래그)를 {lang}으로 사용하여 패턴 팩을 자동 탐색한다.

Glob patterns/{lang}-*.md → Read 각 파일
Glob custom/patterns/{lang}-*.md → Read (사용자 커스텀 패턴 추가 로드)

skip-patterns에 해당하는 팩은 탐색 결과에서 제외한다.

참고: 설정 파일의 patterns 목록은 기본 언어의 팩을 문서화하는 역할이며, 실제 로딩에는 사용되지 않는다. 모든 언어에서 Glob patterns/{lang}-*.md로 자동 탐색한다. 특정 팩을 제외하려면 skip-patterns를 사용한다.

패턴 팩을 두 그룹으로 분류한다:

  • 구조 패턴 (phase: structure frontmatter를 가진 팩): 5a단계에서 먼저 처리
  • 문장/어휘 패턴 (나머지 모든 팩): 5b단계에서 처리

이 분류는 각 팩의 frontmatter에 의해 결정되며, 팩 이름이나 순서와 무관하다.


3단계: Document Type 로드

Glob custom/document-types/{document-type}.md → 있으면 Read
Read document-types/{document-type}.md

커스텀 문서 유형이 있으면 우선 사용한다. 둘 다 없으면 document-types/default.md를 사용한다. namuwiki는 한국어 전용이므로 다른 언어에서는 default로 폴백한다.

문서 유형의 frontmatter에서 purpose, audience, structure, style, avoid, pattern-overrides를 읽어 4.8단계 문서 브리프와 5단계 패턴 처리에 적용한다. Markdown 본문은 문서로만 취급한다. Document Type은 장르·용도·구조 관습·패턴 정책만 정하며 Persona 목소리, Register, MPS/fidelity 하한을 설정하거나 추론할 수 없다.


4단계: 기본 목소리와 Persona 로드

Read core/voice.md
Glob custom/personas/{lang}/{persona}.md → 명시한 persona가 있으면 Read
Read personas/{lang}/{persona}.md → 커스텀이 없을 때

core/voice.md는 모든 rewrite에 적용되는 기본 편집 원칙이다. Persona가 생략되면 원문 목소리를 보존한다. Persona가 있으면 YAML frontmatter의 목소리 블록만 적용하고 Markdown 본문은 문서로만 취급한다. Persona는 Document Type, Register, 패턴 정책, MPS/fidelity 하한을 바꿀 수 없다.


4.5단계: 의미 앵커 추출 (Semantic Anchor Extraction)

입력 텍스트에서 의미 보존이 필요한 핵심 앵커를 추출한다. 이 앵커 목록은 내부 작업 메모리로만 사용되며 사용자에게 출력하지 않는다.

건너뜀 조건
주의: 텍스트가 1개 단락 이하이고 2개 문장 이하이면 추출을 건너뛰고 파이프라인을 정상 실행한다 (오버헤드 불필요).
참고: 앵커 추출이 건너뛰어지거나 추출된 앵커가 0개이면, MPS는 N/A로 표시되며 검증 게이트의 MPS 하한을 적용하지 않는다.
앵커 유형
유형캡처 대상예시
Claim사실적 주장, 결론"시스템이 실패했다", "매출이 30% 증가했다"
Polarity긍정/부정/중립 입장"검증되지 않았다" → 부정
Causation인과 관계"A가 B를 유발했다", "X 때문에 Y가 발생했다"
Quantifier수치, 정도, 범위"p<0.05", "약 3배", "대부분"
Negation부정 표현"하지 않는다", "불가능하다", "결코"
추출 규칙
  • 명시적으로 서술된 의미만 추출한다. 행간의 의미나 함의는 추출하지 않는다.
  • 단락당 최대 3개 앵커를 추출한다 (검증 비용 상한).
  • 각 앵커는 {type, content, paragraph_index, polarity} 형태로 기록한다.
  • 앵커 목록은 내부 작업 메모리이며 사용자 대면 출력에 포함하지 않는다.
  • 앵커 구조는 언어와 무관하다. 추출은 원문 언어로 수행한다.

4.6단계: 통계 기반 의심 구간 탐지 (Stylometric Suspect Zone Detection)

패턴 카탈로그가 명명하지 못하는 분포적 AI다움(균질한 문장 길이, 빈약한 어휘 다양성)을 결정론적 통계로 미리 표시한다. 4.5단계 의미 앵커와 마찬가지로 이 결과는 내부 작업 메모리이며 사용자 대면 출력에 포함하지 않는다.

건너뜀 조건
주의: 텍스트가 단락 ≤2 또는 전체 문장 ≤2 이면 4.6단계를 통째로 건너뛴다 (4.5단계와 동일 임계).
언어 제한: stylometry.languages 설정에 포함된 언어에서만 실행한다. 기본값은 [ko, en, zh, ja]. 처리 언어가 zh 또는 ja 인 경우 whitespace 단어가 아니라 문자 토큰 fallback으로 4.6단계를 실행한다.
메트릭 정의

전체 알고리즘 정의는 core/stylometry.md를 참조한다. 핵심 공식만 인라인으로 제시한다.

Tokenization — ko/en은 whitespace 기준 분할 + edge-punctuation strip(ko=어절, en=단어)을 사용한다. zh/ja는 Han/Kana 문자와 ASCII run을 토큰으로 삼는 deterministic character-token fallback을 사용한다. 형태소 분석기 미사용.

Korean advisory metadata (translationese, koPostEditese.v1)

Korean deterministic analysis may surface analysis.translationese and top-level koPostEditese / koPostEditese.v1 as rewrite editing hints: calque candidates, literal pronouns, by-passives, double particles, uniform endings, rhythm, and suffix-diversity proxies. These hints are advisory context only for natural Korean editing and are separate from the 4.6/4.7 hot-zone computation. They must not feed or alter score, hot 판정, gates, benchmark claims, severity, z-score/baseline/percentile logic, prompt/rewrite gates, or authorship verdicts.

Burstiness (CV, 문장 길이 변동성)

sentence_token_counts = [len(tokens) for sentence in paragraph]
mean = sum(...) / N
stddev = sqrt(sum((x - mean)^2) / N) # population stddev
burstiness_CV = stddev / mean

밴드: low < 0.30 / 0.30 ≤ mid ≤ 0.50 / high > 0.50. (v3.5.1 calibration)

MATTR (Moving Average TTR, 어휘 다양성)

window = 50 tokens
lower_tokens = [token.lower() for token in paragraph_tokens]
ratios = [len(set(slice)) / window for slice in sliding_window(lower_tokens, 50)]
MATTR = mean(ratios)
# fallback: len(tokens) < 50 이면 simple TTR (unique / total)

밴드: low < 0.55 / 0.55 ≤ mid ≤ 0.70 / high > 0.70. lowercase 외 추가 정규화 없음 (no stemming/lemmatization).

Hot 판정 규칙 (4.6 단독 신호)

paragraph is SUSPECT iff burstiness_band == "low" OR MATTR_band == "low"
주의: 위 2신호는 4.6단계가 단독으로 계산하는 부분 규칙이다. 최종 hot 판정은 4.7단계의 통합 OR 규칙(lexicon, KO 진단 복합, discourse tells, ending monotony, 문서 레벨 신호 포함)으로 결정된다.
LLM 전달 형식

원문 텍스트 상단에 meta block 을 삽입하고, hot 단락 본문 첫머리에 prefix 토큰을 부착한다.

Meta Block (예)

<suspect-zones lang="ko">
- P2: burstiness=0.18 (low), MATTR=0.48 (low) — 문장 길이 균질, 어휘 반복 다수
</suspect-zones>

Body Prefix (예)

«P2 SUSPECT» 이 도구는 단순한 자동완성을 넘어선다. ...
파이프라인 결합
  • 5a 단계: 입력에 meta block + prefix 가 포함된 상태로 전달된다. hot 단락이 우선 검토 대상이다.
  • 5b 단계: 동일 입력을 받는다. hot 단락이 우선 재작성 대상이다.
  • 5c 단계: 최종 출력에서 meta block 과 prefix 가 모두 제거되었는지 확인한다. 처리되지 않은 hot zone 이 있으면 경고한다 (강제 재처리는 v1 범위 밖).
주의: suspect zone 정보는 사용자 대면 출력에 노출하지 않는다. 4.5단계 anchor 와 동일한 "내부 작업 메모리" 정책이다.

4.7단계: AI-lexicon 매칭 (AI-Lexicon Overlap Detection)

28-패턴 카탈로그가 명명하지 못하는 AI 특유 어구(예: transformative, cutting-edge, unlock the potential, 자리매김, 결론적으로)를 평면 사전(flat dictionary)으로 추가 매칭한다. 4.6단계가 분포적 신호(문장 길이 균질, 어휘 반복)라면, 4.7단계는 어휘적 신호 — 다른 축이라 OR 결합으로 합산 효과를 낸다. 4.5/4.6단계와 마찬가지로 결과는 내부 작업 메모리이며 사용자 대면 출력에 포함하지 않는다. (v2.0 렉시콘부터 외부 검증된 고정밀 카탈로그 앵커는 사전에 중복 수록된다 — lexicon/ai-ko.md 헤더 참조.)

건너뜀 조건
주의: 텍스트가 단락 ≤2 또는 전체 문장 ≤2 이면 4.7단계를 통째로 건너뛴다 (4.6단계와 동일 임계).
언어 제한: lexicon.languages 설정에 포함된 언어에서만 실행한다. 기본값은 [en, ko, zh, ja]. zh/ja는 character-token fallback 특성상 기본 사전을 phrase-only로 유지한다.
사전 로드
Glob lexicon/ai-{lang}.md → Read
Glob custom/lexicon/ai-{lang}.md → Read (사용자 커스텀 우선)

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 93 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

  • SKILL.md in the repositoryCheckingSKILL.md

Popularity

Repository stars
344
Repository forks
34
7-day trend score
29

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 26 Apr 2026, 6 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/devswha/patina/patina/badge)](https://verified-skill.com/skills/devswha/patina/patina)

Something wrong with this skill or its page? Tell us.