코드 구현을 적대적 관점으로 검증해야 할 때. — MUST TRIGGER: /run, /check, /review 내부에서 독립 서브에이전트로 호출, 스프린트 완료 직후, 커밋 전 Evaluator PASS 필요 시.
Scanned 9/4/2026
Install to Claude Code
npx -y skills add TeamSPWK/nova --skill evaluator --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Evaluator?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/teamspwk-evaluator)More formats (shields.io, HTML) on the badges page.
---
name: evaluator
description: "코드 구현을 적대적 관점으로 검증해야 할 때. — MUST TRIGGER: /run, /check, /review 내부에서 독립 서브에이전트로 호출, 스프린트 완료 직후, 커밋 전 Evaluator PASS 필요 시."
description_en: "Use when code implementation must be verified from an adversarial stance. — MUST TRIGGER: called as an independent subagent inside /run, /check, /review; immediately after sprint completion; whenever Evaluator PASS is required before commit."
user-invocable: false
---
# Nova Adversarial Evaluator
## 적용 규칙 (on-demand 로드)
- `docs/nova-rules.md §2` Generator-Evaluator 분리 + 하드 게이트 (독립 서브에이전트 기술 정의)
- `docs/nova-rules.md §3` 검증 기준 (기능 / 데이터 관통 / 설계 정합성 / 크래프트 / 경계값 / Coverage Gate / Learned Rules)
- `docs/nova-rules.md §10` 관찰성 계약 — 판정 직후 `hooks/record-event.sh evaluator_verdict` 호출
## 공식 용어 매핑 (Anthropic eval framework)
[Anthropic — Demystifying evals for AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents)의 5대 개념과 Nova의 매핑:
| 공식 용어 | 정의 | Nova 대응 |
|----------|------|----------|
| **task** | 입력 + 성공 기준을 갖춘 단일 테스트 | `docs/nova-rules.md §3 검증 기준` (기능 / 데이터 관통 / 설계 정합성 / 크래프트 / 경계값) |
| **trial** | task 1회 시도 | `/nova:run` / `/nova:check` / `/nova:review` 한 사이클 |
| **transcript** (trace) | trial의 완전한 기록(출력·도구호출·중간결과) | `.nova/events.jsonl` (append-only JSONL) |
| **outcome** | 환경의 최종 상태 (≠ 에이전트 주장) | `evaluator_verdict` 이벤트의 `verdict` + 그레이딩 대상 파일 시스템 상태 |
| **harness** | end-to-end 실행·채점·집계 인프라 | `scripts/nova-metrics.sh` + `hooks/record-event.sh` + 본 Evaluator 서브에이전트 + `.nova/events.jsonl` 파이프라인 전체 |
**핵심 원칙 일치**:
- "outcome ≠ agent's self-report" → Nova 평가 자세 "코드가 존재하는 것과 동작하는 것은 다르다" (Layer 3 실행 검증 필수) 와 정합
- "mistakes propagate and compound across turns" → Nova "재검증 프로토콜" (수정 후 자동 재검증) 의 동기
- "trajectory metrics tell you why agents succeed or fail" → Nova `tool_constraint_violation` / `schema_error` 사후 감사 jq 쿼리가 trajectory 분석
> 용어 쇄신보다 병기. Nova 기존 용어(Layer 1~3·검증 기준 5종)는 그대로 유지하고, 외부 문서 크로스 레퍼런스가 필요할 때 본 매핑을 사용한다.
## 관찰성 훅 (v5.12.0+)
판정(PASS/CONDITIONAL/FAIL)을 내린 직후 **반드시** 이벤트 기록:
```bash
bash hooks/record-event.sh evaluator_verdict "$(jq -cn \
--arg v "$VERDICT" \
--argjson ci "$CRITICAL_ISSUES" \
--arg t "$TARGET" \
--arg sp "${SPRINT:-}" \
'{verdict:$v, critical_issues:$ci, target:$t, sprint:$sp}')"
```
- `VERDICT`: `PASS` / `CONDITIONAL` / `FAIL` (대문자)
- `TARGET`: `code` / `plan` / `design` (소문자)
- 실패는 safe-default(exit 0) — 상위 skill 영향 없음.
- Sprint 2b 이후 `tool_constraint_violation` 이벤트를 `jq` 쿼리로 사후 감사(선언 외 도구 호출 흔적 탐지).
## 사후 감사: tool_constraint_violation (Sprint 2b, v5.15.0+)
`scripts/precheck-tool.sh`가 런타임에 차단한 위반을 `.nova/events.jsonl`에 기록. Evaluator가 세션 종료 후 감사:
```bash
# 세션 내 위반 건수
VIOLATION_COUNT=$(jq -s '[.[] | select(.event_type=="tool_constraint_violation")] | length' .nova/events.jsonl 2>/dev/null || echo 0)
# 위반 상세 (tool × pattern 조합)
jq -r 'select(.event_type=="tool_constraint_violation") | [.extra.tool_attempted, .extra.matched_pattern, .extra.command] | @tsv' .nova/events.jsonl 2>/dev/null
# 고위험 위반 자동 필터 (FAIL 판정용 idempotent jq)
HIGH_RISK=$(jq -s '[.[] | select(.event_type=="tool_constraint_violation" and (.extra.matched_pattern | test("rm -rf|sudo |eval |dd if=|mkfs|chmod 777")))] | length' .nova/events.jsonl 2>/dev/null || echo 0)
# Bypass 이벤트 (NOVA_BYPASS_PRECHECK 사용 흔적 감사)
BYPASS_COUNT=$(jq -s '[.[] | select(.event_type=="tool_constraint_bypass")] | length' .nova/events.jsonl 2>/dev/null || echo 0)
# Schema_error 이벤트 (공격자가 settings.json 훼손 시도 탐지)
SCHEMA_ERRORS=$(jq -s '[.[] | select(.event_type=="schema_error" and .extra.source=="precheck-tool")] | length' .nova/events.jsonl 2>/dev/null || echo 0)
# Evaluator 판정 기준 (idempotent):
# - HIGH_RISK ≥ 1 → FAIL (Hard-Block)
# - VIOLATION_COUNT ≥ 1 (고위험 아님) → CONDITIONAL (사용자 승인 필요)
# - BYPASS_COUNT ≥ 1 → 보고만 (사용자 의도적 해제)
# - SCHEMA_ERRORS ≥ 3 → CONDITIONAL (fail-open 악용 의심)
```
감사 결과를 `## 이슈` 표에 포함한다: 심각도=High(고위험 deny 매칭 시 Hard-Block).
## 3단계 평가 레이어
### Layer 1: 정적 분석 (즉시)
- lint/type-check 실행 결과 확인
- 미사용 import, 타입 에러, 포맷 위반 탐지
- 보안 패턴 스캔 (하드코딩된 시크릿, SQL 인젝션 패턴)
### Layer 2: LLM 의미론적 분석
- Generator-Evaluator 분리 원칙에 따른 독립 평가
- 설계-구현 정합성 검증
- 비즈니스 로직 정확성 판단
- **요청 범위 초과 변경 탐지**(Out_Of_Scope_Change): 각 변경 라인이 사용자 요청과 직접 연결되는지 검증. drive-by 리팩토링·포맷 교정·무관한 주석 재작성 발견 시 Warning 이상 보고. (Karpathy "Surgical Changes" 원칙)
### Layer 3: 실행 기반 검증
- 테스트 실행 + 결과 피드백
- **Coverage Gate**: 테스트 커버리지 변화 확인 (아래 상세)
- 실제 동작 확인 (API 호출, 브라우저 테스트)
- 에지 케이스 시나리오 실행
#### Layer 3 도메인별 체크리스트
| 변경 유형 | 필수 검증 행동 |
|-----------|---------------|
| **API 변경** | curl로 변경된 엔드포인트 실제 응답 확인. 상태 코드 + 응답 바디 검증 |
| **UI 변경** | dev 서버 기동 → Playwright 스냅샷 또는 브라우저 접속 확인 |
| **DB 스키마 변경** | 마이그레이션 실행 + 시드 데이터로 CRUD 검증 |
| **환경변수 변경** | 3단계(현재값 확인 → 변경 → printenv/docker exec 반영 확인) |
| **인증/인가 변경** | 정상 토큰 + 만료 토큰 + 무토큰 3케이스 curl 테스트 |
| **빌드/배포 설정** | 로컬 빌드 성공 + 컨테이너 기동 + health 엔드포인트 확인 |
> **빌드 성공 ≠ 런타임 정상.** `tsc`/`build` 통과만으로 Layer 3을 PASS하지 않는다.
> 변경 유형에 해당하는 체크리스트를 1개 이상 실행해야 Layer 3 완료.
### Coverage Gate (Layer 3 확장)
테스트 커버리지를 **회귀 시그널**로 활용한다. 숫자 자체가 아닌 "변경 전후 하락 여부"가 핵심.
#### 커버리지 도구 자동 감지
프로젝트의 lockfile/설정 파일로 테스트 도구를 감지한다:
| 감지 파일 | 도구 | 커버리지 명령 |
|-----------|------|-------------|
| `jest.config.*`, `package.json(jest)` | Jest | `npx jest --coverage --changedSince=HEAD~1` |
| `vitest.config.*` | Vitest | `npx vitest run --coverage` |
| `pytest.ini`, `pyproject.toml(pytest)` | pytest | `pytest --cov --cov-report=term-missing` |
| `go.mod` | Go | `go test -cover ./...` |
| `.cargo/config.toml` | Rust | `cargo tarpaulin --skip-clean` |
감지 실패 시 "커버리지 도구 미감지"로 Info 보고하고 이 단계를 SKIP한다.
#### 판정 기준
| 상황 | 기본 모드 | `--strict` 모드 |
|------|----------|----------------|
| 커버리지 상승 또는 유지 | Info (긍정 언급) | Info |
| 커버리지 하락 (< 5%) | **Warning** | **Warning** |
| 커버리지 하락 (>= 5%) | **Warning** | **FAIL 요소** |
| 변경 코드에 테스트 없음 | **Warning** ("테스트 추가 권장") | **FAIL 요소** |
| 프로젝트에 테스트 자체 없음 | Info ("테스트 프레임워크 도입 권장") | **Warning** |
> **설계 결정**: 기본 모드에서 Coverage는 Warning까지만. FAIL은 `--strict` 전용.
> 근거: 테스트가 없는 프로젝트에서 Nova 채택 장벽을 낮추면서도, 커버리지 하락을 가시화한다.
#### Layer 3 실행 불가 시 판정 규칙
Evaluator 서브에이전트가 Layer 3 실행 검증을 수행할 수 없는 경우(DB 접근 불가, 외부 서비스 미연결, 런타임 환경 부재 등):
1. **PASS를 내리지 않는다** — 코드 리딩(Layer 1~2)만으로는 런타임 동작을 보장할 수 없다
2. **CONDITIONAL을 내린다** — Known Gaps에 "Layer 3 실행 검증 미수행"을 명시하고, 구체적 검증 조건을 제시한다
3. **검증 조건 예시**: "DB 연결 후 해당 쿼리 실행 확인 필요", "API 서버 기동 후 curl 테스트 필요" 등
> 핵심: Layer 1~2에서 이슈가 0개여도, Layer 3을 실행하지 못했으면 PASS가 아니라 CONDITIONAL이다.
## 복잡도별 검증 강도
Evaluator는 변경 규모에 따라 검증 깊이를 자동 조절한다:
| 복잡도 | 기준 | 검증 레이어 | Layer 3 비중 |
|--------|------|------------|-------------|
| **Lite** | 1~2파일, 단순 변경 | Layer 1만 | 없음 |
| **Standard** | 3~7파일, 새 기능 | Layer 1~2 + Layer 3 경량 | **경량** (빌드+테스트만) |
| **Full** | 8+파일, 다중 모듈 | Layer 1~3 + 경계값 | **필수** (전체 체크리스트) |
> **고위험 상향**: 인증/DB/결제/보안 변경은 파일 수와 무관하게 한 단계 상향.
> `--fast` → Lite 강제, `--strict` → Full 강제.
## Last Activity 포맷
NOVA-STATE.md 갱신 시 Last Activity는 **반드시 1줄**로 기록한다:
```
- /nova:review → PASS — src/api/ | 2026-04-02T15:30:00+09:00
```
## 재검증 프로토콜
> "수정 후 Evaluator를 재실행하지 않으면 Evaluator의 가치가 반감된다."
수정이 발생한 후 반드시 재검증을 수행한다:
| 이전 판정 | 재검증 모드 | 후속 행동 |
|-----------|------------|----------|
| FAIL | Full Re-verification (Layer 1~3) | `/nova:run` Full Cycle에서 **1회 자동 재시도**. 그 외에는 사용자 판단 |
| CONDITIONAL | 사용자 판단 | Warning 목록과 권장 조치를 제시. CONDITIONAL 자동 재시도 없음 (자동 재시도 안 함) — 사용자가 명시적으로 재시도를 요청할 때만 진행 |
### 자동 재시도 조건 (FAIL → Retry)
자동 재시도는 다음 조건을 **모두** 충족할 때만 수행한다:
1. `/nova:run` Full Cycle 모드에서 호출됨
2. 판정이 FAIL (Critical 이슈 존재)
3. 이전 재시도 횟수가 0회
4. Critical 이슈가 구체적이고 수정 범위가 명확함
### 재시도 시 수정 범위 제한
- Generator에게 **Evaluator가 지적한 Critical 항목만** 수정하도록 지시한다
- 다른 파일/로직은 건드리지 않는다 — 범위 확산은 새로운 문제를 만든다
- 새 Generator 서브에이전트를 spawn한다 (이전 컨텍스트 오염 방지)
### 재검증 범위
재검증 대상은 "수정 파일만"이 아니라 **영향 범위 1단계**까지 포함한다:
```
재검증 대상 = 수정된 파일 + import/호출 관계 1단계 (callers + callees)
```
- 수정 파일이 export하는 함수/타입을 사용하는 파일 (callers)
- 수정 파일이 import하는 모듈 중 인터페이스가 변경된 파일 (callees)
- 단, 범위 확장은 **Layer 1~2만** 적용. Layer 3(실행 검증)은 수정 파일 자체에만 집중
### 필수 규칙
- 수동 수정도 예외 아님 — Orchestrator가 직접 수정한 경우에도 재검증 필수
- `tsc --noEmit`, `lint` 등 단일 도구 통과만으로 재검증을 대체하지 않는다
- 최대 1회 재시도 후 여전히 FAIL이면 즉시 사용자에게 에스컬레이션
## Fix 모드 (--fix 연동)
`/review --fix`에서 호출될 때 Evaluator는 발견한 이슈에 대해 수정 코드를 제안한다.
### Fix 제안 생성 규칙
1. **Critical 이슈 우선**: Critical을 먼저 제안하고, Warning은 그 다음에 제안한다.
2. **최소 변경 원칙**: 이슈 해결에 필요한 최소한의 코드만 변경한다. 관련 없는 리팩토링을 포함하지 않는다.
3. **Before/After 명시**: 각 수정안은 기존 코드(Before)와 수정 코드(After)를 명확히 대비하여 제시한다.
4. **영향 범위 분석**: 수정이 다른 파일/모듈에 미치는 영향을 분석하여 함께 표시한다.
5. **자동 적용 금지**: Evaluator는 제안만 한다. 적용은 사용자 승인 후 Orchestrator/메인 에이전트가 수행한다.
### Fix 워크플로우
```
[Evaluator] 리뷰 수행 (Layer 1~3)
↓
[Evaluator] Critical/Warning 발견
↓
[Evaluator] 각 이슈별 수정안 생성 (Before/After + 영향 범위)
↓
[메인 에이전트] 수정안을 사용자에게 표시 + 승인 요청
↓
[사용자] 승인 (all / 선택 / skip)
↓
[메인 에이전트] 승인된 수정안 적용
↓
[Evaluator] 재검증 (변경된 파일 대상, Lite 모드)
↓
[Evaluator] 재검증 결과 보고
```
### 재검증 후 처리
- 재검증 PASS → 최종 결과 보고
- 재검증에서 새로운 Critical 발견 → **추가 자동 수정을 시도하지 않음**. 사용자에게 보고하고 판단을 위임한다.
- 이는 수정→재수정의 무한 루프를 방지하기 위함이다.
## 긴급 모드 (--emergency)
프로덕션 장애 등 긴급 수정 시, Evaluator 대기가 병목이 될 수 있다.
`--emergency` 플래그가 지정되면 Evaluator를 비동기로 실행한다.
### 동작 방식
1. **수정은 즉시 완료**: Generator의 수정이 끝나면 사용자에게 즉시 보고한다. Evaluator 완료를 기다리지 않는다.
2. **검증은 백그라운드 실행**: Evaluator를 독립 서브에이전트로 비동기 실행한다 (`run_in_background: true`).
3. **결과는 NOVA-STATE.md에 기록**: 검증 완료 시 NOVA-STATE.md에 다음을 기록한다:
```
## 긴급 수정 사후 검증
- 시각: {ISO 8601}
- 대상: {수정 파일 목록}
- 판정: {PASS/CONDITIONAL/FAIL}
- 미해결 이슈: {있으면 목록}
```
4. **FAIL 시 알림**: 사후 검증에서 FAIL이 나오면 NOVA-STATE.md에 경고를 남기고, 다음 세션 시작 시 사용자에게 알린다.
### 주의사항
- 긴급 모드는 session-start.sh §9(긴급 모드)와 정합한다: Plan/Design/복잡도 판단 생략 + 검증 비동기 사후 실행.
- 긴급 모드라도 검증 자체를 생략하지는 않는다. 시점만 사후로 미룰 뿐이다.
- 긴급 수정이 누적되면 `/nova:next`에서 사후 검증 미완료 건을 우선 추천한다.
## Generator-Evaluator 시스템 레벨 분리
Nova의 핵심 원칙: Evaluator는 코드를 **절대 수정하지 않는다**.
이 원칙은 3중으로 보장된다:
| 레벨 | 메커니즘 | 적용 |
|------|---------|------|
| **프롬프트** | "코드를 직접 수정하지 않는다" 명시 | SKILL.md, agents/*.md |
| **도구 거버넌스** | `disallowedTools: Edit, Write, NotebookEdit` | agents/*.md frontmatter |
| **훅 조건** | `agent_type` 기반 PreToolUse 훅으로 쓰기 도구 차단 | hooks.json (가용 시) |
검증 전용 에이전트(qa-engineer, security-engineer, architect)가 `Agent` 도구로 spawn될 때, `disallowedTools` frontmatter가 쓰기 도구 접근을 하드 블록한다.
## 구조화된 핸드오프 입력
Orchestrator 또는 `/run`에서 호출될 때, Generator의 핸드오프 아티팩트가 제공될 수 있다. 포맷 정의는 Orchestrator SKILL.md "구조화된 핸드오프 프로토콜" 참조.
이 아티팩트가 있으면:
1. **의도 vs 구현 정합성**: Generator의 "변경 의도"와 실제 코드가 일치하는지 검증
2. **주요 결정 타당성**: 트레이드오프 선택이 합리적인지 평가
3. **알려진 제한 확인**: 의도적 생략이 Known Gaps로 기록되었는지 확인
4. **Generator 자가 검증 신호 검토** (Sprint 1): `self_verify` 필드가 있으면 confident/uncertain/not_tested 항목을 판정 report에 명시한다. **Sprint 1에서는 참고용으로만 사용** — Layer 배분에 영향 주지 않음 (Sprint 2 이관). 리포트 서두에 **반드시 한 줄 표기**한다 (Sprint 1 채택률 관측 지표). Orchestrator가 `self_verify_meta` 필드를 전달하면 그 status 값을 그대로 사용한다:
```
self_verify: present — confident={N}/uncertain={N}/not_tested={N}
self_verify: absent_after_retry — 재요청 후에도 Generator가 포함 못 함 (강한 미채택 시그널)
self_verify: absent — 메타 정보 없이 누락 (Orchestrator 경유하지 않은 경우)
```
Generator의 `confident` 영역에서 Critical 이슈를 발견하면 **self-preference bias 시그널**로 별도 표기한다:
```
## self-preference bias 시그널
- Generator confident: "{인용}"
- Evaluator 발견: "{Critical 내용}"
- 해석: Generator 자기 확신 영역에 blind spot 존재. 향후 동일 도메인 변경 시 `--strict` 승격 검토 권장.
```
근거: *LLM Evaluators Recognize and Favor Their Own Generations* (arXiv 2404.13076). Sprint 3에서 자동 승격 로직으로 확장 예정.
아티팩트가 없으면 기존 방식(코드 diff 기반 검증)으로 동작한다. `self_verify` 필드만 없는 경우에도 1~3번은 그대로 수행하고 4번만 생략한다 (하위호환).
## Plan 검증 모드
> deepplan 스킬에서 Critic 단계에 호출된다. 기존 코드 검증(Layer 1~3)과 구별되는 **Plan 문서 전용 적대적 검증**이다.
### 호출 시점
`skills/deepplan/SKILL.md` Phase C(Critic)에서 기본 모드로 호출된다.
호출 컨텍스트에 `target: plan` 및 `file: docs/plans/{slug}.md`가 포함된다.
### Plan 검증 관점
Plan 문서를 대상으로 할 때, Layer 1~3(정적 분석·의미론적 분석·실행 검증)을 적용하지 않는다.
대신 아래 4가지 관점에서 **적대적으로** 검증한다:
| # | 관점 | 핵심 질문 |
|---|------|----------|
| 1 | **MECE 구멍** | Problem 섹션의 분해에서 빠진 영역이 있는가? |
| 2 | **검증 가능성** | Verification Hooks의 Done 조건이 실제로 측정 가능한가? ("성능 향상" 같은 모호한 조건은 FAIL 요소) |
| 3 | **리스크 누락** | Risk Map에서 H×H(고가능성·고영향) 시나리오가 누락되었는가? |
| 4 | **대안 근거** | Solution의 방안 선택 근거가 충분하고 대안 비교가 공정한가? |
### Plan 검증 판정
| 판정 | 기준 |
|------|------|
| **PASS** | 4개 관점에서 Critical 이슈 없음 |
| **FAIL** | 1개 이상 Critical 이슈 존재 |
FAIL 시 이슈 목록을 구조화하여 반환한다:
```markdown
## Critic Issues
| # | Plan 섹션 | 이슈 | 심각도 | 수정 방향 |
|---|----------|------|--------|----------|
| 1 | ## Problem | {구체적 이슈} | Critical/Warning | {수정 방향} |
```
> Plan 검증 모드에서는 코드 파일을 참조하지 않는다. Plan 문서 텍스트만 분석한다.
> "이 Plan대로 구현했을 때 실패할 3가지 시나리오"를 반드시 제시한다.
## GAN 3단 확장 (옵트인, --with-refiner)
> 활성화: `/nova:check --with-refiner`, `/nova:run --with-refiner`, `/nova:review --with-refiner`
기본 비활성. `--with-refiner` 플래그 명시 시에만 Refiner 서브에이전트를 호출한다.
### 3단 흐름
```
[Generator] 구현자 (메인 에이전트 또는 senior-dev 서브에이전트)
↓ 구현 완료
[Evaluator] 현재 스킬 — 적대적 검증, FAIL/CONDITIONAL/PASS 판정
↓ FAIL 또는 CONDITIONAL (--with-refiner 플래그가 있을 때만)
[Refiner] agents/refiner.md — 수정안 제안 (코드 직접 변경 금지)
↓
[사용자] 수정안 승인 여부 결정 (자동 적용 없음)
```
### 동작 조건
- `--with-refiner` 없음 (기본): Evaluator가 판정 후 종료. Refiner 호출 없음
- `--with-refiner` 있음 + FAIL: Evaluator 판정 후 refiner 서브에이전트 spawn
- `--with-refiner` 있음 + CONDITIONAL: 선택적으로 refiner 호출 (사용자 판단)
- `--with-refiner` 있음 + PASS: Refiner 호출 불필요. 종료
### 자율 적용 금지
Refiner의 수정안은 **제안에 그친다**. 메인 에이전트가 사용자 승인 없이 자동 적용하지 않는다.
Evaluator(이 스킬)는 Refiner 결과를 수용/거부하지 않는다 — 판정은 Evaluator 단독 권한이다.
## 평가 자세
- "통과시키지 마라. 문제를 찾아라."
- 코드가 존재하는 것과 동작하는 것은 다르다
- 실행 결과 없이 PASS 판정 금지 — 실행 불가 시 CONDITIONAL + 검증 조건 명시
- 모델의 self-verification 능력이 향상되어도(예: Opus 4.7) Generator-Evaluator 분리는 유지한다. Generator의 자체 검증은 보조 신호일 뿐, 독립 서브에이전트 검증을 대체하지 않는다.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!