# QC 규칙 (Quality Control Rules)

## [CRITICAL] hooks와 QC는 별개 의무

hooks(pyright/ruff 자동 실행)가 통과했더라도 QC 의무는 면제되지 않는다.

- hooks: 정적 분석 자동화 도구 (type check, style check)
- QC: 기능 정확성, 비즈니스 로직, 요구사항 충족 여부 검증

hooks 통과 ≠ QC 면제. 두 프로세스는 독립적으로 수행되어야 한다.

**버전**: 3.0 (2026-03-12, Agency-Agents 패턴 적용: Fantasy Approval 방지, Evidence 필수, Zero Issue Red Flag)
**이전 버전**: 2.5 (테스트 회귀 방지 규칙 신설)

프롬프트에서 `level` 값을 전달받습니다. 해당 레벨에 맞는 섹션을 모두 수행하세요.
- **normal**: 셀프 QC + 자동 검증
- **critical**: normal 전체 + 마아트 독립 검증
- **security**: critical 전체 + 로키 보안 감사

---

## 1. 셀프 QC (모든 레벨 공통, 아누 가이드 3.4 System 2 Forcing)

### 1-A. 기본 체크리스트 (모든 작업에 항상 적용)

보고서를 작성하기 전에 반드시 아래 8항목을 스스로 점검하고 각 항목에 대한 답을 확인하세요:
- [ ] 1. 이 변경이 다른 파일에 영향을 미치는가? (영향 파일 목록 명시)
- [ ] 2. 이 로직의 엣지 케이스는 무엇인가? (빈 값, 경계값, 예외 경로)
- [ ] 3. 이 구현이 작업 지시와 정확히 일치하는가?
- [ ] 4. 에러 처리와 보안은 확인했는가?
- [ ] 5. 테스트가 모든 경로를 커버하는가?
- [ ] 6. 발견한 이슈를 모두 직접 해결했는가? (범위 외 사유 없이 미해결로 남긴 이슈가 없는가?)
- [ ] 7. 코드 아키텍처 원칙(`memory/specs/code-architecture-principles.md`)을 확인했는가? — SOLID/DRY 위반 없음 확인
- [ ] 8. 인터페이스(API/함수 시그니처) 변경 시 관련 문서를 갱신했는가?
- [ ] 9. 이미지/배너 작업: .html 파일이 있으면 대응 .png 렌더링 파일도 존재하는가? (HTML만 있고 PNG 없음 = 미완료)
- [ ] 10. CLAUDE.md 100줄 미만 확인 (팀 고유 CLAUDE.md가 비대해지면 QC WARN 발생)
- [ ] 11. 3문서 업데이트 (Lv.3+): plan.md/context-notes.md/checklist.md가 존재하면 status 업데이트 + 체크리스트 체크 완료
- [ ] 12. 3 Step Why (Lv.3+): A-B-C 답변이 context-notes.md에 기록되었고 논리적 일관성 확인
- [ ] 13. L1 스모크테스트: 실제 서버/UI/API 동작 확인 완료 (pytest만으로 불충분)
- [ ] 14. 듀얼 MCP 검증 (프론트 변경 시): Playwright 스크린샷 + Chrome DevTools Lighthouse/콘솔 에러 기록 완료

---

### 1-C. Agency-Agents 품질 원칙 (v3.0 신설)

아래 4개 원칙은 모든 QC 판정에 적용됩니다.

#### "기본값 NEEDS WORK" 원칙
- 모든 QC의 기본 판정은 **NEEDS WORK**. 증거로 뒤집어야 PASS.
- 주장만으로는 PASS 불가. 테스트 결과, 스크린샷, 로그 등 증거 첨부 의무.

#### Zero Issue = Red Flag
- 첫 구현에서 이슈 0건은 비현실적. **최소 3개 이슈를 발견**해야 함.
- 이슈 0건 보고 시 QC 판정자가 재검증 요청.

#### Fantasy Approval 탐지
- 다음 표현 사용 금지: "모든 것이 완벽합니다", "A+ 품질", "문제 없음", "이상 무"
- 반드시 정량적 증거 포함 (테스트 통과율, 커버리지 %, 응답시간 ms 등)
- 정성적 판단("깔끔한 코드")은 정량적 근거("pyright 에러 0건, black 준수")로 뒷받침

#### Evidence 필수 규칙
- 모든 PASS 판정에는 최소 1개의 증거가 첨부되어야 함
- 허용 증거: pytest 결과, pyright 출력, 스크린샷, API 응답 로그, 커버리지 보고서
- 증거 없는 PASS = 자동 NEEDS WORK로 격하

---

### 1-D. 이슈 처리 규칙 (필수)

- 작업 중 발견한 이슈는 **직접 해결 후 보고**가 원칙
- "발견했습니다" 끝 → 금지. 해결 과정까지 포함해야 보고 완료
- 해결 과정은 로그에 기록 (어떤 파일을 왜 어떻게 수정했는지)
- 보고서에는 요약만 기재, 상세는 <details> 블록 또는 별도 섹션으로 분리
- 범위 외 이슈만 미해결 허용 (사유 필수 명시: 다른 팀 소관, 외부 의존성 등)

---

### 1-E. 보안 및 PII 검사 규칙 (v3.8 신설)

#### OWASP 보안 검사
- security 레벨 작업 또는 인증/결제 관련 코드 변경 시, `/owasp-security --quick` 실행 필수
- 검사 결과를 보고서 하단에 포함
- CRITICAL/HIGH 발견 시 수정 후 재검사
- 참조: `/owasp-security` 스킬 (OWASP Top 10 보안 검사, Python/TypeScript/SQL 특화)

#### PII 노출 검사
- 보험/금융 데이터 처리 코드 변경 시, `/sanitize --report` 실행하여 PII 노출 여부 확인
- owasp-security와 보완적 관계: owasp-security=보안취약점, sanitize=PII(개인식별정보)
- 검사 대상: 주민등록번호, 계좌번호, 보험 증권번호 등 한국 PII 10개 유형
- 참조: `/sanitize` 스킬 (한국 PII 탐지 및 마스킹)

---

### 1-F. 재시도 상한 규칙 (v4.1 신설)

- 같은 task에서 .done 제출 → QC FAIL → 재작업 → 재제출 **최대 3회**
- 재시도 횟수는 `memory/events/{task_id}.retry_count` 파일로 추적
- qc_verify.py `--gate` 모드에서 FAIL 시 자동으로 카운터 증가
- **3회 초과 시 에스컬레이션**:
  - qc_verify.py가 "ESCALATE" 상태 반환
  - .done 생성 차단
  - 에스컬레이션 파일 생성: `memory/events/{task_id}.escalate`
  - 콘솔 경고: "⚠️ task-XXXX 재시도 3회 초과. 아누 판단 필요."
  - 아누(Anu)가 판단하여 수동 해결 또는 재시도 카운터 초기화

---

## 2. 자동 검증 (모든 레벨 공통, qc_verify.py)

셀프 QC 완료 후 자동 검증 스크립트를 실행하세요:

```bash
python3 /home/jay/workspace/teams/dev1/qc/qc_verify.py --task-id <TASK_ID> [--skip api_health]  # 서버 작업이 아니면 api_health 스킵
```

- 서버/API 작업: `--api-base http://localhost:<PORT> --api-endpoints /api/status,/api/...`
- 테스트 실행: `--test-dir <TEST_DIR>` (기본: 스킵)
- 특정 파일 확인: `--check-files path1,path2` (pyright_check도 이 파일들을 대상으로 실행)
- `workers/` 하위에 `models.py`가 존재하면 `schema_contract` verifier 자동 활성화 (별도 플래그 불필요)
- 결과가 FAIL이면 해당 항목을 수정한 후 재실행하세요.
- 결과 JSON을 보고서 하단에 포함하세요.

### test_runner 대상 범위 규칙 (v3.3 신설)
- `--check-files` 지정 시: 관련 테스트 파일을 자동 추론하여 해당 테스트만 실행
- `--test-dir tests/` (전체 디렉토리): 금지. 본인 작업 무관 실패 포함 위험
- `--skip test_runner`: 원칙적 금지. 사용 시 MANUAL_SKIP으로 기록 + 경고
- 관련 테스트 파일이 0개: 정당한 SKIP (자동 처리)

### verifier 목록 (v2.3)

| verifier | 검증 내용 | FAIL 조건 | 도입 시기 |
|----------|-----------|-----------|----------|
| api_health | HTTP 200 응답 여부 | 비정상 응답 | v1.0 |
| file_check | 보고서 파일 존재 + 크기 | 파일 없거나 0 bytes | v1.0 |
| data_integrity | task-timers.json ↔ .done 파일 교차 검증 | 상태 불일치 | v1.0 |
| test_runner | pytest exit code | 0이 아닌 경우 | v1.0 |
| tdd_check | TDD 순서 검증 (테스트 먼저 작성 여부) | 구현만 있고 테스트 없음 | **v2.3** |
| schema_contract | 스키마 계약 검증 (상세 아래) | 아래 참조 | **v2.0** |
| pyright_check | pyright LSP 타입 체크 | 심각한 타입 에러 존재 시 | **v2.1** |
| style_check | Python 코드 스타일(black+isort) 검증 | — (WARN만) | **v2.2** |
| scope_check | 변경 범위 검증 (예상 파일 ↔ 실제 변경 대조) | — (WARN만) | **v2.2** |
| claude_md_check | 팀 CLAUDE.md 줄 수 검증 | — (WARN만) | **v3.6** |
| three_docs_check | 3문서 존재/내용/완료율 검증 (Lv.3+) | 파일 누락 또는 YAML 파싱 실패 | **v4.0** |
| browser_verify | 프론트 변경 시 듀얼 MCP 검증 증거 확인 (스크린샷 + Lighthouse) | 프론트 변경인데 스크린샷 없음 | **v4.2** |

### schema_contract verifier 검증 항목

| # | 검증 항목 | FAIL/WARN |
|---|-----------|-----------|
| SC-1 | Worker 디렉토리에 `models.py` 존재 | FAIL |
| SC-2 | Worker 디렉토리에 `tests/test_contract.py` 존재 | FAIL |
| SC-3 | `shared/schemas/{name}.schema.json` 존재 | FAIL |
| SC-4 | `sample.normal.json` → JSON Schema 검증 통과 (`jsonschema`) | FAIL |
| SC-5 | `sample.edge.json` → JSON Schema 검증 통과 (`jsonschema`) | FAIL |
| SC-6 | Pydantic 모델 필드 목록 ↔ JSON Schema properties 일치 | FAIL |
| SC-7 | sample.json 최근 변경 + Zod 스키마 미변경 감지 | WARN |
| SC-8 | Pydantic v1 문법 (`schema()`) 사용 탐지 | WARN |

**실행 방법**: `workers/` 디렉토리에 `models.py`가 존재하면 자동 활성화. 별도 플래그 불필요.

### tdd_check verifier 검증 항목

| # | 검증 항목 | FAIL/WARN |
|---|-----------|-----------|
| TDD-1 | audit-trail에서 테스트 파일이 구현 파일보다 먼저 수정됨 | PASS |
| TDD-2 | 테스트 파일 없이 구현 파일만 변경됨 | FAIL |
| TDD-3 | 구현 파일이 테스트 파일보다 먼저 수정됨 (TDD 순서 위반) | WARN |
| TDD-4 | audit-trail에 task_id 없으면 --check-files 기반 fallback | — |

**적용 기준**: Lv.2+ 코딩 작업에만 의미 있음. Lv.1 단순 수정/설정/문서 작업은 SKIP 처리.
**테스트 파일 판별**: `test_*.py`, `*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx`, `/tests/` 또는 `/test/` 디렉토리 포함.

### three_docs_check verifier 검증 항목 (Lv.3+ 작업 전용)

- 3문서 디렉토리(`memory/plans/tasks/{task_id}/`) 존재 시 자동 실행
- PASS: 3문서 존재 + YAML 유효 + status 업데이트 + 플레이스홀더 제거 + 체크리스트 50%+
- WARN: 부분 미충족 (작업은 계속 가능)
- FAIL: 디렉토리 존재하나 파일 누락 또는 YAML 파싱 실패
- SKIP: 디렉토리 미존재 (Lv.2 이하 작업 = 정상)

---

## 3. 테스트 회귀 방지 (v2.5 신설, 블로커 규칙)

아래 3개 규칙은 **무조건 준수**합니다. 위반 시 작업 완료 처리 불가.

### 규칙 1: pytest 실패 시 완료 처리 금지
- qc_verify.py의 test_runner 결과가 FAIL이면 **작업 완료(.done) 금지**
- 실패 테스트가 "본인 작업 범위 밖"이라도 **보고서에 반드시 명시**
- 보고서 기재 형식: `⚠️ 기존 테스트 실패 N건 (본 작업 범위 외): [테스트명]`
- 본인 범위 밖 실패는 수정 의무 없지만, **무시/누락은 금지**

### 규칙 2: 코드 변경 시 관련 테스트 동시 수정 의무
- 파일 `X.py`를 변경했으면, `test_X.py` (또는 `tests/test_X.py`)가 존재하는지 확인
- 존재하면: 변경한 인터페이스(함수 시그니처, 출력 형식 등)에 맞게 테스트도 갱신
- **"코드는 바꿨는데 테스트는 안 바꿈" = QC 실패**

### 규칙 3: 테스트 회귀 = 블로커
- 작업 전에 통과하던 테스트가 작업 후 실패하면 **테스트 회귀(regression)**
- 테스트 회귀는 본인 작업이 원인이든 아니든 **블로커로 취급**
- 블로커 해소 방법: (a) 직접 수정 또는 (b) 보고서에 회귀 원인 분석 + 수정 불가 사유 명시

### 규칙 4: 점진적 테스트 (파일 단위 검증)
- 파일 단위로 점진적 테스트 — 전체 작성 후 일괄 테스트 금지
- 각 파일/모듈 수정 후 즉시 해당 테스트 실행하여 통과 확인
- 대규모 변경 시: 파일 1 수정 → 테스트 → 파일 2 수정 → 테스트 → ... (순차적)
- 일괄 작성 후 일괄 테스트하면 실패 원인 특정이 어려워 디버깅 비용 증가

---

## 4. Suppression 목록 (DO NOT flag) (v3.1 신설, gstack A12)

QC에서 아래 패턴은 **의도적으로 경고하지 않는다**. 이들은 노이즈를 생성하여 중요한 이슈를 묻히게 하는 항목이다.

### DO NOT flag 목록

1. **가독성 중복 경고**: 이미 명확한 코드에 "더 읽기 쉽게 리팩터링하라"는 제안
2. **코멘트 부패 위험 경고**: "이 주석이 코드와 불일치할 수 있다" 수준의 추측성 경고
3. **이미 수정된 항목**: PR/커밋에서 이미 수정된 이슈를 다시 지적하는 것
4. **스타일 취향 차이**: black/isort가 이미 적용된 코드에 대한 추가 스타일 제안
5. **과도한 타입 힌트 요구**: 내부 헬퍼 함수, 1회성 람다 등에 타입 힌트 부재 지적
6. **불필요한 docstring 요구**: 자명한 함수(get_name, is_valid 등)에 docstring 부재 지적
7. **테스트 코드 스타일**: 테스트 코드의 매직 넘버, 하드코딩된 값 등 (테스트는 명시적이어야 함)

### Suppression 목록 관리 규칙

- 새 항목 추가 시 반드시 **사유(왜 노이즈인지)** 명시
- 분기별 검토: 여전히 유효한지 확인 (크로노스 회고에서 검토)
- Suppression된 항목이라도 CRITICAL/HIGH 심각도면 예외 없이 보고

---

## 4.5. 산출물 파일 표기 규칙 (v3.5 신설)

- 산출물 파일은 **개별 파일 경로를 각각 나열**할 것
- 축약형(`slide{1-5}.png`, `*.py` 등) 사용 금지
- 각 파일이 대시보드에서 클릭 → 내용 확인 가능해야 함
- 올바른 예시:
  - `output/meta-ads/angle-A/hybrid-v3/recruiting-angleA-hybrid-slide1-v3.png`
  - `output/meta-ads/angle-A/hybrid-v3/recruiting-angleA-hybrid-slide2-v3.png`
  - `output/meta-ads/angle-A/hybrid-v3/recruiting-angleA-hybrid-slide3-v3.png`
- 잘못된 예시:
  - `output/meta-ads/angle-A/hybrid-v3/slide{1-5}-v3.png (5개)`

---

## 4.7. TRUST 5 품질 차원 (v3.6 신설)

> Phase 2-4 도입. `trust5_tagging_enabled` feature flag 활성화 시 QC 결과에 TRUST 요약이 포함된다.

QC verifier들을 5개 품질 차원으로 분류하여 결과를 구조화한다.

### 차원 정의

| 차원 | 의미 | 매핑 verifier |
|------|------|--------------|
| **T**ested | 테스트 검증 완료 | test_runner, tdd_check |
| **R**eadable | 코드 가독성/타입 안전 | style_check, pyright_check |
| **U**nified | 변경 범위 정합성 | scope_check |
| **S**ecured | 스키마/계약 보안 | schema_contract |
| **T**rackable | 데이터 추적 가능성 | data_integrity, file_check |

- 각 차원 내 모든 verifier가 PASS여야 해당 차원이 passed=True
- SKIP된 verifier는 차원 판정에 영향 없음 (FAIL만 차단)
- api_health는 TRUST 외 독립 실행 (차원에 미포함)

### qc_verify.py 구현 요구사항

각 팀의 qc_verify.py에 아래 상수와 함수가 존재해야 한다:

- `TRUST_MAP`: 차원→verifier 매핑 딕셔너리
- `TRUST_INDEPENDENT`: TRUST 외 독립 verifier 목록
- `_build_trust_summary(checks)`: checks 결과에서 TRUST 5차원 요약 생성
- `build_result()`: `trust5_tagging_enabled` 플래그 활성화 시 `trust_summary` 필드 포함

---

## 5. 에러 처리 원칙 (v2.0 신규)

### 데이터 파싱 실패 처리

| 상황 | 처리 방법 | 근거 |
|------|-----------|------|
| Worker 출력 Pydantic 검증 실패 | 예외 발생, Firestore 저장 중단 | 잘못된 데이터 저장 차단 |
| Frontend Zod 파싱 실패 | ZodError 발생 → React Error Boundary 캐치 | 묵음 실패 제거 |
| Error Boundary 트리거 | 사용자에게 에러 메시지 표시 | 투명한 실패 |
| 파싱 실패 이벤트 | Sentry 에러 알람 전송 | 즉시 감지 + 대응 |

**원칙**: "잘못된 데이터의 묵음 표시"는 허용하지 않습니다.
         파싱 실패는 명시적으로 실패해야 합니다.

---

## 6. 수정 파일별 검증 상태 (v4.1 신설, task-1881)

보고서 작성 시 각 수정 파일에 대해 planned(계획) vs verified(검증됨) 상태를 반드시 구분하세요:

**형식:**
```
| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| dispatch.py:854 | --month 인자 추가 | grep "--month" OK | verified |
| routes_get.py:1870 | idle 리셋 | grep "idle" OK | verified |
```

- **planned** = 계획만 세움 (구현 미확인)
- **verified** = grep/테스트로 실제 존재 확인됨
- **[x] 기준** = "L1 스모크테스트 + L2 QC 검증 통과" (단순 코드 작성 완료가 아님)
- ★ planned 항목이 1건이라도 있으면 .done 생성 금지
- Edit 직후 반드시 grep으로 변경 반영을 확인하세요. grep 0건 = Edit 실패입니다.

---

## 변경 이력

| 버전 | 일시 | 변경 내용 |
|------|------|-----------|
| 1.0 | (이전) | 셀프 QC 5항목, qc_verify.py 4개 verifier |
| 2.0 | 2026-03-04 | 셀프 QC 조건부 구조화 (1-A/1-B 분리), 인터페이스 계약 관리 섹션 신설, schema_contract verifier 추가 (SC-1~SC-8), 마아트 독립 검증에 계약 테스트 재실행 의무화, 에러 처리 원칙 명시 |
| 2.1 | 2026-03-06 | pyright_check verifier 추가, --check-files 설명 보강, LSP 우선 사용 규칙 연동 |
| 2.2 | 2026-03-06 | style_check verifier 추가 (black+isort 검증), scope_check verifier 추가 (변경 범위 대조) |
| 2.3 | 2026-03-06 | tdd_check verifier 추가 (TDD 순서 검증), TDD 적용 기준 명시 (Lv.2+) |
| 2.4 | 2026-03-07 | 레벨 분리: Section 1-B, 1.5, 3, 4를 QC-RULES-EXTENDED.md로 분리 |
| 2.5 | 2026-03-08 | 테스트 회귀 방지 규칙 3종 신설 (pytest 실패=블로커, 테스트 동시 수정 의무, 회귀=블로커) |
| 3.0 | 2026-03-12 | Agency-Agents 패턴 적용: "기본값 NEEDS WORK" 원칙, Zero Issue Red Flag, Fantasy Approval 탐지, Evidence 필수 규칙 (1-C 섹션 신설) |
| 3.1 | 2026-03-15 | Suppression 목록(DO NOT flag) 섹션 신설 (gstack A12, task-566.1) |
| 3.2 | 2026-03-15 | 이슈 처리 규칙(1-D) 신설, 셀프 QC 체크리스트에 항목 6 추가 (task-576.1) |
| 3.3 | 2026-03-18 | test_runner 대상 범위 규칙 신설: --check-files 자동 추론, MANUAL_SKIP 도입 (task-688.1) |
| 3.4 | 2026-03-26 | 셀프 QC 체크리스트에 항목 7, 8 추가 (코드 아키텍처 원칙 확인, 인터페이스 변경 시 문서 갱신) (task-1061.1) |
| 3.5 | 2026-03-28 | 산출물 파일 표기 규칙 신설: 개별 파일 경로 나열 필수, 축약형 금지 (task-1169.1) |
| 3.6 | 2026-04-01 | TRUST 5 품질 차원 섹션 신설 (task-1309.1) |
| 3.7 | 2026-04-04 | PNG 렌더링 필수 게이트 추가: 셀프 QC 항목 9 신설 (HTML 배너 → PNG 존재 확인) (task-1421.1) |
| 3.8 | 2026-04-12 | 보안 및 PII 검사 규칙 신설: OWASP 보안 검사 + PII 노출 검사 의무화 (task-1721.1) |
| 4.0 | 2026-04-16 | 3문서 검증 항목 추가: 셀프 QC 항목 11 + three_docs_check verifier 설명 (task-1872_6.5) |
| 4.1 | 2026-04-16 | 수정 파일별 검증 상태(planned/verified) 섹션 신설, Edit grep 리마인더 추가 (task-1881) |

> 데이터 계약/마아트/로키 규칙은 QC-RULES-EXTENDED.md 참조
