vignette/docs/redteam/REDTEAM_FINDINGS.md
Yun Chan 709baadd01 chore: Vignette 모노레포 초기 스캐폴드 + 설계 문서 이관
- apps/web(React) · apps/api(FastAPI) · infra(Docker) · docs(설계 SoT)
- 마스터플랜·적대검증·메모리설계·디자인컨셉 docs 이관
- 미성년 사례데이터는 .gitignore로 제외(개인정보 보호)
2026-06-25 21:16:45 +09:00

296 lines
39 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# RED TEAM 종합 결함 보고서 — 한신대 AI 심리상담 시뮬레이션 플랫폼 마스터플랜
> 적대적 검증 일자: 2026-06-25
> 대상: `HANSHIN_AI_PLATFORM_MASTERPLAN.md` + 9개 하위 설계서
> 검증 렌즈 7종: 요구충실도 / 엔진실현성 / 오케스트레이션·구현 / 음성 / 데이터·학술·윤리 / 통합·E2E / 보안·운영·비용
> 종합 방식: 7개 렌즈 결함을 중복 병합, 심각도 정렬, 카테고리 분류, 고유 ID(F-NN) 부여
---
## ⚡ 최우선 강조 — 윤찬 원래요구를 위반/타협/축소한 항목 (이것이 핵심)
마스터플랜이 **비용·동시성·안전·일정을 명분으로 윤찬의 신성불가침 요구를 깎은** 지점들이다. 윤찬 작업원칙상 "요구를 지키면서 문제를 푸는 것"이 정답이지, 요구를 깎는 것은 결함이다.
| ID | 위반한 요구 | 무엇을 깎았나 | 심각도 |
|---|---|---|---|
| **F-01** | **요구3 (엔진=로컬 claude -p)** | 기본 엔진을 `claude -p`에서 **Anthropic Messages API(종량제)로 바꿔치기**, claude -p를 "옵션 플래그·시연용"으로 격하. 같은 프로젝트 하위 설계서 2종(음성·3AI)은 정반대로 claude -p를 기본 엔진으로 못박아 **문서 간 정면 모순** | **BLOCKER** |
| **F-02** | **요구7 (음성 무조건)** | "무조건"인 음성을 우선순위 P1·Phase 2(9~15주)로 격하, 첫 외부 시연(Phase 1)에서 음성 통째 누락. 일정 1주만 밀려도 음성이 잘릴 구조 | **BLOCKER** |
| **F-03** | **요구3+요구5/16 충돌** | claude -p(요구3)가 backend Presidio 마스킹 게이트를 **우회**해 미성년 원문을 Anthropic에 직송 가능 → "데이터 로컬 미이탈" 주장 부분 거짓, 미성년 보호(요구5/16)와 구조적 충돌 | **BLOCKER** |
| **F-08** | **요구7 (s2s 결정권)** | OpenAI Realtime s2s를 윤찬 동의 없이 "탈락" 단독 확정(월권). 탈락의 1번 근거가 "claude -p 고정"인데 F-01이 그걸 풀어버려 **근거 자기붕괴**. "transcript 없음" 근거도 OpenAI 실제 스펙(`input_audio_transcription`)과 불일치한 허수아비 | **MAJOR** |
| **F-09** | **요구6 (지속적 판단)** | "지속적으로 잘못 판단"인데 정밀평가(deep-loop)를 "회기말"로 미뤄 *판단 자체가 지연*되는 것처럼 축소(판단은 지속·제시만 회기말로 분리했어야) | **MAJOR** |
| **F-10** | **요구에 없는 제약 추가** | 윤찬이 요구한 적 없는 **"자유연습 서버단 하드 차단"**을 람다가 임의 도입(교수자 통제권 침해). CARE RCT 근거는 경고·기본값 추천으로 족함 | **MAJOR** |
| **F-11** | **요구16 (IRB 불필요)** | 헤더만 "IRB 불필요"로 패치하고 **본문(Phase 0/3 게이트·액션Top5·체크리스트)에 IRB 신청·승인 의존성 잔존** → 부분 수정 누락, 팀이 불필요한 IRB 리드타임 소모 위험 | **MAJOR** |
| **F-12** | **요구3 (엔진 일관성)** | 매 발화 도는 fast-loop 평가 AI를 로컬 claude -p가 아닌 **외부 Haiku/Solar API**로 기본 설정 → 요구3 취지(로컬·정액·데이터주권) 이탈, 윤찬 명시 승인 없는 타협 | **MAJOR** |
> **핵심 한 줄:** 마스터플랜은 *무엇을 만들지(WHAT)*는 정교하나, 윤찬의 두 기둥 **로컬 claude -p 엔진**과 **음성 무조건**을 비용·안전 명분으로 깎았고, 그 깎음이 자기 하위 설계서와 논리적으로 모순된다. 해법(프로세스 풀, 어댑터 default 교체, s2s 2차 옵션화, `--input-format stream-json` 상주)은 이미 하위 문서에 적혀 있는데도 요구를 깎는 쪽을 택한 것이 최대 결함이다.
---
## 🔴 BLOCKER 등급
### F-01. [원래요구위반] 엔진을 claude -p → Messages API로 바꿔치기 (요구3 전복) + 문서 간 자기모순
- **카테고리:** 원래요구위반 / 기술결함
- **병합 출처:** requirements F1 · engine F-1 · voice V-3 · integration F2 · security B1
- **근거:** 마스터플랜 §0 표 "기본=Anthropic Messages API … `claude -p`(Max OAuth)는 옵션 플래그·개발 시연용", §5/§4 트랙 A "Messages API 직결", 다이어그램 "①claude_api(기본) ②claude_cli(옵션)". **자기모순:** 음성설계서 §0/§1/§2.2와 3AI설계서 D-4는 claude -p를 **기본 엔진으로 고정**. 두 문서가 동시에 참일 수 없음.
- **원래요구위반:** **명백.** 요구3은 "엔진 = 로컬 PC Opus 4.8 claude code -p" 명시. 격하 근거 3개 전부 약함:
1. "과금 누수 $1,800" = 종량제 API 위험이지 `claude -p`(Max OAuth 정액) 위험 아님. claude -p는 Max rate limit 내 한계비용 0(음성설계서 §7.1 자인). **논리 오류.**
2. "동시성 1프로세스 한계" = 음성설계서 §6이 이미 browser-pool식 프로세스 풀로 해결책 명시. 거짓 제약.
3. "rate limit 마비" = 파일럿 20명 규모, Max ×3 구독에서 근거 빈약(측정 없이 단정, `feedback_measure_before_report` 위반).
- **수정방향:** 어댑터 구조는 유지하되 **default provider를 `claude_cli`로 복원**, Messages API는 폴백 옵션으로 강등(1줄 교체). 동시성은 프로세스 풀+세션 캡, 비용은 정액이라 한계 0. Phase 1 DoD를 "P1 내담자 응답이 로컬 claude -p로 생성·스트리밍"으로 재작성. **엔진 기본값 변경은 윤찬 명시 승인 사안(`feedback_no_blanket_overwrite`)** — 되돌려 확인.
### F-02. [원래요구위반] "음성 무조건"을 P1·Phase 2로 격하, 첫 외부 시연에서 음성 누락
- **카테고리:** 원래요구위반
- **병합 출처:** requirements F2 · voice V-1
- **근거:** Phase 1 완료기준 "P1 내담자와 **텍스트 상담**"(음성 0), Phase 2(9~15주) "음성 + 3역할…" 우선순위 **P1**. 음성설계서 M4(13~17주)에야 chanpaca.net 음성 시연.
- **원래요구위반:** 요구7 "음성 채팅 **무조건**" = P0 언어. 외부 데모(요구4) 첫 인상에 음성 없음. R12(일정압박) 현실화 시 가장 먼저 잘릴 P1 블록 + IRB·3역할과 한 Phase에 뭉쳐 슬립 시 음성 통째 증발 구조.
- **수정방향:** Phase 1 완료기준에 "P1 1페르소나·1보이스 캐스케이드 음성 왕복 1턴 PoC" 추가(얇게라도 "무조건"을 일정으로 증명). Phase 2에서 음성을 IRB·3역할과 **분리 독립 트랙**으로. (OpenAI gpt-4o-mini-tts 사용은 요구7 충족 인정.)
### F-03. [데이터·윤리/원래요구위반] claude -p가 Presidio 마스킹 게이트 우회 → 미성년 원문 Anthropic 직송 (요구3 vs 요구5/16 충돌)
- **카테고리:** 데이터·윤리 / 원래요구위반
- **병합 출처:** security M4
- **근거:** §3.3 "저장 전 PII 마스킹 하드게이트: **backend→외부 LLM 경로**에 Presidio", §1.1 "데이터는 로컬을 떠나지 않음". 그러나 claude -p는 윤찬 PC에서 직접 Anthropic 클라우드(Opus 4.8) 호출 → backend 미들웨어 우회 가능.
- **원래요구위반:** 요구3(claude -p)와 요구5/16(미성년 개인정보 보호)이 구조적 충돌. "로컬 미이탈"은 부분 거짓 — 추론 프롬프트는 해외 전송됨.
- **수정방향:** 엔진 어댑터가 claude_cli일 때도 **프롬프트를 Presidio 통과 후** claude -p에 전달(우회 경로 차단). §1.1 문구를 "마스킹된 텍스트만 Anthropic 포함 외부로"로 정정. 공문/처리방침에 "가명처리본 해외(Anthropic) 전송" 명시. 민감구간은 Solar/HyperCLOVA 국내 라우팅 우선.
### F-04. [데이터·윤리] 전체 학습·평가 시스템이 단일 사례(n=1) 축어록 위에 구축 — "골든셋"이 통계 신뢰도를 위장
- **카테고리:** 데이터·윤리
- **병합 출처:** data B1 · integration F6(부분)
- **근거:** 실측 — `데이터/2026-06-25_프로토콜_축어록/`에 축어록 단 1개(고2 남학생, 단회기). taxonomy 설계서 "파란 라벨 89개·77종"(라벨당 평균 1.15회), 0615 125턴이 (a)평가 정답셋 (b)페르소나 학습신호 (c)재귀학습 시드 (d)κ/ICC 모집단 역할을 **동시에** 수행. 설계서 스스로 "세부코드 κ 낮을 수밖에 없다" 자인.
- **원래요구위반:** 요구13(학술 엄밀 "빡세게")·요구5(재귀축적)를 데이터 기반 부재로 형식 충족 주장. n=1 빈약함이 리스크 등록부에서 누락.
- **수정방향:** "골든셋"→"시드 1례(seed exemplar), 신뢰도 측정 불가"로 정직 표기. Phase 0의 "골든셋 50발화"를 **"한신대 추가 축어록 N건 수급"을 블로킹 의존성으로 격상**(공문 액션에 누락됨). 페르소나 시드와 평가 정답 데이터를 분리(train/test 누수 차단).
### F-05. [데이터·윤리/원래요구위반] 미성년·자살사고 사례의 "재귀학습 축적"이 IRB 면제와 양립 불가 — 요구5와 요구16 충돌을 봉합만 함
- **카테고리:** 데이터·윤리 / 원래요구위반
- **병합 출처:** data B2
- **근거:** §3.3 "원본 축어록 DB 절대 미적재"라면서, taxonomy §8은 0615 원문 발화 125턴을 `turns.text`에 적재해 재귀학습 원천화 → **자기모순**. 헤더는 "IRB 불필요 즉시 착수"의 안도감으로 데이터 거버넌스 폭탄을 "공문 확인 유지" 한 줄로 격하.
- **원래요구위반:** 요구16 "미성년 원본 활용동의는 별도"를 **선행 게이트가 아닌 후행 확인**으로 처리 = 축소. "IRB 면제"는 *수련생 실험* 면제이지 *미성년 사례데이터 활용* 면제가 아님.
- **수정방향:** 법정대리인 동의서에 "AI 학습데이터 2차 가공·DB 영구축적·파생모델 배포"를 별도 동의항목으로 분리, 동의 전 0615 적재 금지를 Phase 0 hard gate로. 자살사고 미성년 발화는 **합성·환언된 CCD 스펙만** 학습원천, 원문은 audit 보존용 격리.
### F-06. [데이터·윤리] 타당도 미검증 평가 AI가 수련생 20명을 먼저 가르친 뒤 사후에 신뢰도를 잰다 — 오학습 순환구조
- **카테고리:** 데이터·윤리
- **병합 출처:** data B3
- **근거:** §2.2 deep-loop "0-5 채점+대안발화", §2.3 "κ≥0.6/ICC≥0.75 게이트 통과분만 골든셋 승격". 그런데 그 타당도는 §3.3/R3 기준 **20명 파일럿에서야 측정**. CARE 인용으로 자유연습 차단(피드백 필수)했으나 그 피드백 타당도는 미검증 → 저품질 피드백 = 본인 인용대로 "오학습 유발". 거짓양성이 옳은 인간중심 개입(의도적 침묵)을 "수동적"으로 오교정할 위험.
- **원래요구위반:** 요구6 "지속 판단"·요구13을 형식 충족(타당도 보증이 사용 시점보다 늦음).
- **수정방향:** 평가 AI 타당도를 **수련생 노출 전** 별도 검증셋(F-04 해결 전제)에서 LLM-judge κ 확보, 미달 차원은 학습자에 **점수 비노출(코칭만)**. 초기 deep-loop는 단정 채점 금지·"관찰" 프레이밍. 거짓양성률 정량 임계 + 파일럿 1차 지표 승격.
### F-07. [기술결함] 음성 전송계층(WSS)이 마스터플랜 인프라 토폴로지에서 통째 누락 — 음성이 외부에서 동작할 E2E 경로 없음
- **카테고리:** 기술결함
- **병합 출처:** integration F1 · voice V-5(부분) · security M1(부분)
- **근거:** 마스터플랜 §1.1에 음성 등장 안 함, 외부노출은 전부 SSE(Tailscale Funnel)로만. 그러나 음성설계서 §4.1 "캐스케이드는 브라우저 mic PCM 업스트림 → SSE 불가 → **WSS 강제**". Cloudflare 터널이 WSS 양방향 바이너리 PCM을 어떻게 프록시할지, stream.chanpaca.net이 WSS도 받는지 **계약 미정의**. 전송 3종(정적/SSE/WSS)이 한 브라우저 세션에서 서로 다른 인프라.
- **원래요구위반:** 요구7(음성)+요구4(외부공유) E2E를 동시 위협.
- **수정방향:** §1.1에 WSS 음성 경로를 1급 추가(`voice.chanpaca.net` WSS 전용 + Caddy WS upgrade/버퍼링off/`proxy_read_timeout 3600s`). Phase 1 트랙 C에 "50분 WSS 양방향 스트림 끊김 실측"을 SSE 테스트와 함께 DoD화. 전송계층 라우팅 표를 단일 계약으로 고정.
---
## 🟠 MAJOR 등급
### F-08. [원래요구위반] s2s를 윤찬 동의 없이 "탈락" 단독 확정 + 근거 자기붕괴/허수아비
- **카테고리:** 원래요구위반 / 기술결함
- **병합 출처:** requirements F6 · voice V-2
- **근거:** §0 "s2s 1차 탈락". 음성설계서 §2.2 탈락 1번 근거 = "엔진 claude -p 고정" — 그런데 F-01이 그 고정을 풀어 **근거 절반 자기붕괴**. "transcript 없음" 근거도 OpenAI Realtime의 `input_audio_transcription`(입력)·`audio.transcript`(출력) 네이티브 제공을 무시한 허수아비(별도 STT 사이드카 불필요).
- **원래요구위반:** 요구7은 "OpenAI API로 음성 서비스"이지 "캐스케이드만"이 아님. "탈락" 단독 확정은 월권. (단 transcript 보존=평가·재귀학습 1급 자산 논리는 타당 → 캐스케이드 1차는 합리적.)
- **수정방향:** "s2s 탈락"→"**s2s 2차 PoC 옵션 유지**"로 표현 격상(음성설계서 §8이 이미 2차 옵션). 탈락 근거를 transcript 보존 단일 사유로 재정리. 윤찬에 "캐스케이드 1차/s2s 2차" 명시 보고·승인.
### F-09. [원래요구위반] 백그라운드 "지속적 판단"을 회기말로 미뤄 축소
- **카테고리:** 원래요구위반
- **병합 출처:** requirements F4
- **근거:** §2.3 "deep-loop(Opus): 단계 전환·회기말 0-5 채점… 종료 후 대시보드가 SUS↑·인지부하↓".
- **원래요구위반:** 요구6 "지속적으로 판단". fast-loop가 있어 완전 위반은 아니나, 정밀 판단을 UX 명분으로 회기말 배치 = 미세 축소.
- **수정방향:** **"판단은 지속(deep-loop 백그라운드 계속), 제시만 회기말"**로 명확 분리. 현 문구는 판단 자체를 미룬 것처럼 읽힘.
### F-10. [원래요구위반] 윤찬이 요구한 적 없는 "자유연습 서버단 하드 차단" 임의 추가
- **카테고리:** 원래요구위반
- **병합 출처:** requirements F5
- **근거:** §0 "자유연습(피드백 OFF) 기본 차단", §7 "자유연습 비활성화".
- **원래요구위반:** 16개 요구 어디에도 자유연습 차단 없음. Stanford CARE 근거는 있으나 람다가 교수자 통제권을 임의 침해. `feedback_risk_user_decides`(위험은 알리되 차단 강제 권한 없음) 원칙 위배.
- **수정방향:** **기본 ON + 피드백 권장 배지** 또는 **교수자 토글**로. CARE 근거는 UI 경고·기본값 추천으로 제시, 서버 하드차단 제거. (미동의자·미성년 차단은 IRB·개인정보 사안이므로 별개 유지 — 정당.)
### F-11. [원래요구위반/오케스트레이션] IRB 본문 잔재 — 헤더만 패치, Phase·액션·체크리스트에 IRB 의존성 잔존
- **카테고리:** 원래요구위반 / 오케스트레이션·구현능력결함
- **병합 출처:** requirements F7 · (integration·orchestration 플래그)
- **근거:** 헤더 "IRB 불필요" vs 본문 §4 Phase 0 "IRB 신청서 제출", Phase 3 의존성 "+IRB 승인", Phase 3 "20명 IRB 파일럿", §8 액션#2 "IRB 프로토콜 제출 — 승인 리드타임이 Phase 3 게이트", §7 IRB 체크리스트 전체 잔존.
- **원래요구위반:** 요구16 반영 누락(부분 수정). 팀 인계 시 불필요 IRB 리드타임 소모, 제거한 게이트 부활.
- **수정방향:** 본문 전수 정리 — Phase 0 "IRB 신청서 제출" 삭제, Phase 3 의존성에서 "IRB 승인" 제거, §8 액션 IRB 삭제, "IRB 파일럿"→"교육용 파일럿". §7은 **미성년 활용동의+개인정보 처리방침**만 남기고 IRB 심의 항목 전부 제거.
### F-12. [원래요구위반/기술결함] fast-loop 평가 AI를 외부 Haiku/Solar API로 기본 설정 — 요구3 취지 이탈
- **카테고리:** 원래요구위반 / 기술결함
- **병합 출처:** engine F-6 · integration F4
- **근거:** 3AI §3.2 "fast-loop 엔진=Haiku 4.5 또는 Solar Pro 3 직접 API". 매 발화 도는 가장 빈번한 경로가 비-claude·외부 종량제. 매 발화 Presidio 마스킹 지연이 지연예산(<1.5s) 미반영.
- **원래요구위반:** 요구3 취지(로컬·정액·데이터주권) 이탈. 윤찬 명시 승인 없는 타협. ( 발화단위 분류를 Opus로 도는 과잉 약한 위반이라 MAJOR.)
- **수정방향:** fast-loop 기본을 **로컬 1B 분류기(NAS 상주)** 또는 **상주 Haiku claude -p**, 외부 API는 폴백. 어느 경로든 `turns.llm_provider` 적재해 "claude 비중" 측정. 외부 유지 윤찬 승인 + 마스킹 지연을 예산표 반영.
### F-13. [기술결함] claude -p "1턴 후 종료" 모델 vs warm pool 가정 충돌 — 핵심 지연(TTFT 400~900ms) 미검증
- **카테고리:** 기술결함
- **병합 출처:** engine F-4 · voice V-3(부분) · integration F3
- **근거:** 음성설계서 §6 "LLM TTFT ~400~900ms" 측정값 아닌 희망값. "프로세스 워밍으로 콜드스타트 회피" vs 3AI §6.3 "claude -p는 1턴 종료라 warm pool은 SDK/API로 가야 깔끔" **자기반박**. 회기당 30~50턴이면 Node 콜드스타트( ) TTFT에 얹힘.
- **누락된 해법(엔진 렌즈 실측):** CLI v2.1.191에 **`--input-format stream-json`(realtime streaming input)** 실재 단일 상주 프로세스에 턴마다 JSON 주입하는 양방향 멀티턴 모드. 설계서가 플래그를 검토조차 "claude -p로 warm 불가API로" 논리의 전제가 틀림.
- **수정방향:** `--input-format stream-json` 상주 프로세스 + 인스턴스 풀로 **콜드스타트를 회기당 1회로 압축**. Phase 1 DoD에 "상주 claude -p TTFT p50/p95 실측 + 동시 4회기 부하에서 열화곡선·피크 RSS·OOM 0" 게이트 신설. 실측 400~900ms를 계획에 쓰지 (`feedback_measure_before_report`).
### F-14. [기술결함] 1급 claude -p 호출 템플릿이 존재하지 않는 플래그 사용 — "공식 문서 검증됨"이 실바이너리와 불일치
- **카테고리:** 기술결함
- **병합 출처:** engine F-2 · F-3
- **근거(CLI v2.1.191 직접 실행 검증):** 3AI §2.2 "공식 문서 검증됨" 템플릿이 **`--max-turns`(존재하지 않음)** 1턴 강제 메커니즘으로 사용. `--append-system-prompt-file` 메인 help에 없어 미검증. **모드 자기모순:** `--bare` OAuth/keychain 차단(API 강제) 정액(모드A)에서 . 1급 템플릿이 정액 모드와 양립 불가 윤찬이 피하려던 종량제가 기본이 .
- **수정방향:** `--max-turns` 의존 제거(claude -p는 도구 미사용 단일응답 종료가 기본, 폭주는 `--max-budget-usd`). system 주입은 `--system-prompt-file` 실측 확정 또는 stdin JSON 동봉. 정액+재현성은 `--bare` 없이 OAuth + `--settings`(hooks off`--strict-mcp-config`·격리 `HOME`/`CLAUDE_CONFIG_DIR` 글로벌 CLAUDE.md 차단 **윤찬 PC에서 1회 실증 후** "검증됨" 표기.
### F-15. [기술결함] 엔진 어댑터 "한 줄 전환" 주장 미검증 — stream-json/구조화출력/cost 정규화 레이어 부재
- **카테고리:** 기술결함
- **병합 출처:** engine F-5
- **근거:** §0 "어댑터 줄로 전환". 그러나 `claude -p` stream-json 이벤트(`total_cost_usd`, `structured_output`) Messages API SSE(`content_block_delta`, `usage`) 스키마 상이. `MessagesAPIEngine` 구현 부재. cost_usd 의미가 경로에서 달라 재귀학습·비용 텔레메트리(요구5) 일관성 깨짐.
- **수정방향:** `LLMEngine` 정규화 이벤트 스키마 + 정규화 cost 규약(정액은 토큰×참조단가 shadow cost) 정의. 양쪽 어댑터를 Phase 0~1에 구현 + contract test(동일 입력동일 정규화 출력) DoD화.
### F-16. [오케스트레이션·구현능력] 오케스트레이션 주체·구조 부재 — "기존 풀스택팀" 5글자가 인적자원 전부
- **카테고리:** 오케스트레이션·구현능력결함
- **병합 출처:** orchestration D-O1 · D-O7
- **근거:** 마스터플랜 line 4 "기존 풀스택팀", line 305 "인계". 트랙 A/B/C/D를 나눴으나 **소유 주체(인간/람다 TeamCreate/spawn 세션) 매핑 0**. "SSE 스키마 합의 병렬" 합의 주체·산출물·동결 시점 없음. 트랙 A에 어댑터+상태머신+내담자AI+평가AI+가드레일 전부 = 람다 직접제작 회귀 위험.
- **원래요구위반:** " 병렬 오케스트레이션 우선" + "람다는 인프라·감시만, 직접 만들지 마라" 원칙 위배.
- **수정방향:** 트랙별 RACI(소유주체·디렉토리 경계·람다 역할·인터페이스 계약 동결시점). 비대 트랙 A를 sub-트랙으로 분할, 람다는 계약 정의+합류 검증만.
### F-17. [오케스트레이션·구현능력/원래요구위반] 모든 완료기준(DoD)이 결과 서술 — 검증 주체·수단·테스트 하네스 0
- **카테고리:** 오케스트레이션·구현능력결함 / 원래요구위반
- **병합 출처:** orchestration D-O2 · D-O3 · D-O4
- **근거:** Phase 1 DoD "교수님이 상담피드백 수신", Phase 2 "3역할 권한격리 실동작 검증" **누가/어떤 도구로/어떤 절차로** 검증하는지 전무. "교수님이 한다" 검증 외주. subagent가 물리적으로 하는 작업(50분 SSE·실시간 음성 레이턴시·OAuth 콜백) 미배정. 트랙 합류(integration) 소유자·순서 없음.
- **원래요구위반:** `feedback_verify_actual_interaction`(람다 직접 클릭타이핑삭제 검증) 정면 위배 "기능 존재=완료"는 금지된 패턴.
- **수정방향:** DoD에 **검증 프로토콜** 명시 람다가 windows-mcp/Playwriter로 실제 로그인상담 완주피드백 수신 재현, 권한격리는 타인 session_id 직접입력403 스크린샷, 저항엔진은 공감5턴vs조언5턴 openness 곡선 DB쿼리 정량확인. subagent 불가 작업은 백그라운드 Bash+Monitor·실기기·Playwriter로 배정. Phase 통합게이트(람다 E2E 1회 재현).
### F-18. [오케스트레이션·구현능력] 장시간·상태유지 작업(라벨링·검수·κ누적)을 stateless 오케스트레이션으로 끌고 갈 방법 없음
- **카테고리:** 오케스트레이션·구현능력결함
- **병합 출처:** orchestration D-O5
- **근거:** 트랙 D "annotation_round+IAA 게이트, 교수자 검수 κ 누적", "골든셋 50발화 라벨링" 수일~수주 인간-루프. subagent 호출로 불가.
- **수정방향:** 라벨링·검수·κ를 DB/파일 영속 작업으로 재정의, 람다는 크론(CronCreate)+단계 재개 워크플로우로 오케스트레이션. ds 스키마에 체크포인트 저장, 다음 세션 이어받기.
### F-19. [기술결함] 윤찬 PC = 엔진+터널 SPOF, 외부 서비스 가용성 설계 공백
- **카테고리:** 기술결함
- **병합 출처:** security B2 · integration F8
- **근거:** §1.1 로컬 PC/NAS 박스, R10 "NAS SPOF스냅샷/덤프"(데이터 손실 대응이지 가용성 아님). 요구3(엔진=윤찬 PC)+요구4(교수 임의시각 접속) 합치면 PC 절전/재부팅/크래시/OAuth 만료/rate limit/codex node 누수(`reference_codex_node_memory_leak` 전례) 교수 화면 상담 사망. cloudflared·Caddy·Postgres·claude -p·voice-gw가 단일 물리 호스트 수렴.
- **수정방향:** (a)엔진 PC와 NAS DB를 다른 물리 장애도메인 분리, (b)교수 테스트 **예약 슬롯제**+직전 헬스체크(PC alive·세션 워밍·터널 up) 링크 발송, (c)watchdog(claude/cloudflared/docker 자동 재기동)+외부 모니터디코 알림, (d)claude -p 다운 시에만 Messages API 자동 폴백(가용성 안전망). PC 절전/윈도우 업데이트 방지(`.ps1` ASCII 함정 주의).
### F-20. [기술결함/데이터·윤리] SSE 분리 경로(Tailscale Funnel)가 무인증 노출 + `__Host-` 쿠키 인증 붕괴 — 미성년 상담 스트림 IDOR 위험
- **카테고리:** 기술결함 / 데이터·윤리
- **병합 출처:** security M1 · integration F10
- **근거:** §01.1 SSE를 별도 도메인 stream.chanpaca.net + Tailscale Funnel(무인증 공개) 분리. auth-rbac은 `__Host-` 쿠키(Domain 속성 금지) 인증 일원화 **다른 호스트에 쿠키 미전송 → SSE 인증 구조적 붕괴**. Funnel에 RBAC/세션검증 강제 방법 미설계 타인 상담 스트림 무인증 구독(IDOR) 가능. `reference_cloudflared_external_share` 멀티tailnet 함정 전례.
- **수정방향:** SSE도 **단일 도메인+Cloudflare 단일 터널**에서 먼저 실측(heartbeat+`no-transform`+flush -1), 끊길 때만 분리. 분리 불가피 stream 경로도 BFF 경유 + short-lived signed token(쿠키 아닌 header/query, 세션당 1회·단명). WSS(음성SSE(텍스트) 같은 전송 추상화로 통합 검토(노출면 최소화).
### F-21. [데이터·윤리/기술결함] 음성 turn 스키마 ↔ §3.2 DB 스키마 불일치 — paralinguistic 컬럼 부재로 재마이그레이션 폭탄
- **카테고리:** 기술결함 / 데이터·윤리
- **병합 출처:** integration F5
- **근거:** 음성설계서 §10 turn 로그 필수 `{audio_ref, silence_ms, speech_rate, barge_in}` vs §3.2 turns 스키마에 해당 컬럼 없음. Phase 0에서 스키마 확정(DoD=마이그레이션 통과) Phase 2 음성 진입 핵심 평가 feature(침묵자살암시) 담을 없어 재마이그레이션+평가 입력계약 재작업.
- **수정방향:** Phase 0 스키마에 음성 메타 컬럼(nullable) 선반영 또는 `turn_paralinguistic` 1:1 확장 테이블 + `voice_persona_map` 추가. §10 계약을 마스터플랜 스키마에 머지(단일 SoT).
### F-22. [데이터·윤리] DSM-5 반영이 표면적 — 감별진단·C-SSRS 매핑 없이 단일라벨 회피만
- **카테고리:** 데이터·윤리
- **병합 출처:** data M2
- **근거:** §2.4 RDoC 차원 4개(자의적 추출, 정식 6도메인 아님), §7 "DSM-5 차원 프로파일" 미체크. ideation_stage 1~5와 C-SSRS 정식축 매핑표 부재, P1 감별진단(지속성우울/적응장애/주요우울) 없음.
- **원래요구위반:** 요구13 "DSM-5 빡세게 반영" 부분 축소.
- **수정방향:** ideation_stageC-SSRS 매핑표, P1~P3 페르소나의 DSM-5 진단기준행동증거 매트릭스 추가. "진단 비노출" "진단학적 엄밀성" 양립 가능(내부 파라미터).
### F-23. [데이터·윤리] 슈퍼바이저 논평(1인·1회기)을 "AI 피드백 모범 코퍼스"로 일반화 → 편향 주입
- **카테고리:** 데이터·윤리
- **병합 출처:** data M3
- **근거:** taxonomy §3.3 "모범 코멘트 코퍼스". 0615 논평은 슈퍼바이저 1인의 1회기 사후평. "어미 번갈아 쓰면 안정감 저해"(SV.LANG, 현장특이·근거불명)까지 모범화하면 CBT 학습자에 인간중심 미시문체 오적용. F-04(n=1)와 결합해 편향 시스템 증폭.
- **수정방향:** 슈퍼비전 논평은 학습 코퍼스 아닌 few-shot/검증 참조로만, AI 피드백은 EPITOME/CTRS 루브릭 앵커. "(현장 특이)" 항목 학습신호 제외. 슈퍼바이저 다인 확보 1인 편향으로 간주·가중치 다운.
### F-24. [데이터·윤리] 인용 논문 다수가 검증 불가 미래시점 arXiv ID — "적대적 검증 완료" 주장과 모순
- **카테고리:** 데이터·윤리
- **병합 출처:** data M4
- **근거:** 설계서 "WebFetch 적대적 검증 완료" 주장 vs PSI-Bench arXiv 2604.25840, PsychEval 2601.01802, TherapyGym 2603.18008 미래시점 ID 세션 web 검증 불가. 핵심 수치(d=0.72, ICC 0.853, 77.2%) 논문에 의존하는데 ICC 0.853은 출처가 "D3-4 인용"으로만 적혀 추적 불가.
- **수정방향:** 신청서·공문 제출 모든 arXiv ID 실재 확인, preprint vs peer-reviewed 구분, 인용 수치 원문 캡처 증빙. 미확인은 "preprint, 미검증" 라벨. ICC 0.853을 1차 논문으로 명기.
### F-25. [데이터·윤리] Presidio 발화단위 마스킹이 사례단위 준식별자 조합을 못 가림 — 미성년 자살사례 재식별 위험
- **카테고리:** 데이터·윤리
- **병합 출처:** data M5
- **근거:** §3.3 Presidio 마스킹은 직접식별자만. taxonomy CCD "고2 남학생+자퇴+등교거부+자살사고+형비교+이모양육+맞벌이" 조합 = 준식별자 묶음으로 소집단 재식별 가능. PIPC 가명처리의 재식별 위험평가 부재.
- **수정방향:** 사례 메타 재식별 위험평가(motivated intruder test), 학년/나이 범주화, 호소문제 일반화. 학습원천은 원사례 아닌 합성변형(F-05 연동).
### F-26. [기술결함] 교수 검수 weighted-κ→골든셋 승격 루프가 20명 단회기에서 통계 성립 불가 (순환의존)
- **카테고리:** 기술결함 / 데이터·윤리
- **병합 출처:** integration F6
- **근거:** §2.33.2 "κ0.6/ICC0.75 게이트 통과분만 골든셋", 재귀학습이 골든셋을 코퍼스로 (순환). 50~수백 발화로 안정적 κ/ICC 산출 어렵고, 0615 89라벨을 페르소나+평가 정답 이중사용8 액션4) = train/test 누수.
- **수정방향:** 재귀학습을 Phase 3 산출물 아닌 "파이프라인 구축+소량 1차 산출" 톤다운. 0615를 페르소나 시드와 평가 정답으로 분리. 골든셋 목표 표본 명시, 미달 "인프라만 검증, 효과는 후속" 명문화. 1라운드는 교수 단독 라벨로 시드.
### F-27. [오케스트레이션·구현능력/기술결함] 20주에 음성+3역할+페르소나3종+RAG+재귀학습+안전분류기가 Phase 2(7주)에 동시 압축 — 자기 부록 일정과 충돌
- **카테고리:** 오케스트레이션·구현능력결함 / 기술결함
- **병합 출처:** integration F7
- **근거:** Phase 2(9~15주, 7주) 트랙 A(음성B(3역할+OAuth BFFC(페르소나+분류기D(재귀+IAA) 병렬. 그러나 음성설계서 §8은 음성만 20주 전체(M4 통합 13~17주), 3AI §7 프로토타입 4~6주. **음성 단독 로드맵 20주를 7주 한 트랙에 욱여넣음**. "기존 풀스택팀(JS 추정)" FastAPI/asyncio/Presidio/pgvector/Deepgram WS/AudioWorklet을 7주 동시 습득 가정.
- **수정방향:** Phase 2 분할 2a(3역할+OAuth+페르소나, 9~13주), 2b(음성 캐스케이드 1페르소나, 13~17주). 재귀학습 IAA·자살분류기 정밀화는 Phase 3 이연. 음성 M-단계와 Phase 주차를 **단일 간트로 통합**(`feedback_proper_backlog_planning`).
### F-28. [원래요구위반/오케스트레이션] 한신대 SSO 미확인 블로커가 로드맵 게이트에 미반영
- **카테고리:** 오케스트레이션·구현능력결함
- **병합 출처:** security M2
- **근거:** auth설계서 §2.2/R11 한신대 SSO 프로토콜(OIDC vs SAML클레임 미확인. §8 액션#1은 공문이나 Phase 2 "BFF OAuth 2.1" 태연히 배치 납품 직전 SAML 어댑터 미예산 작업 폭발 위험. (사용자 OAuth 2.1+BFF+PKCE 설계 자체는 견고 요구2 충족.)
- **수정방향:** 공문 질의를 Phase 0 게이트 격상(IRB 면제로 SSO가 최장 리드타임 블로커). Google OIDC 단독 진행하되 Authlib provider SAML SP 어댑터 스캐폴드 선반영. "OAuth" 용어가 (사용자 로그인) (엔진 Max OAuth) 혼용되니 분리 명시.
### F-29. [기술결함/원래요구위반] 폴백 시 LLM 토큰 비용 추산 통째 누락 — "claude -p라 0원"이 폴백에서 붕괴
- **카테고리:** 기술결함
- **병합 출처:** security M3
- **근거:** 음성 §7.1 "로컬 claude -p라 한계비용 0, 폴백 별도" 폴백 비용 증발. R9 한국어 토큰 35% 팽창. Opus 4.8 입력$5/출력$25 per 1M, deep-loop이 전체 회기 채점 폴백 LLM 비용이 STT/TTS 압도 가능. 회기당 비용 번도 추산 .
- **수정방향:** 폴백 회기당 LLM 비용 상한 실측(Anthropic count_tokens, tiktoken 금지). 프롬프트 캐싱 필수화(L0~L2 정적 cache_control, Opus 4.8 최소 프리픽스 4096토큰 검증, 읽기 0.1x로 ~90% 절감). deep-loop는 폴백 batch API(50% 할인). cost_usd turn 적재 + 폴백 비율 모니터.
### F-30. [기술결함] visible_to[] / RBAC×cohort / RLS 강제 메커니즘이 3개 설계서에서 명명·모델 불일치
- **카테고리:** 기술결함
- **병합 출처:** integration F9
- **근거:** §3.2 `visible_to[]`(AI 정보비대칭) vs auth-rbac RBAC role+cohort(인간 권한) 같은 "누가 무엇을 보나" 독립 메커니즘으로 구현, 교차점 미정의. auth-rbac은 RLS를 "2차 강화", 마스터플랜 §0은 "RLS 이중강제 기본"으로 **또 모순**. §3.2 스키마에 cohort·account_linking 없음.
- **원래요구위반:** 요구8(3페이지 권한격리) 강제 메커니즘 비일관.
- **수정방향:** visible_to[](AI) RBAC×cohort(인간) 다른 레이어로 명시 분리, 교차점(인간이 turn 읽을 게이트 AND) 단일 enforcement 미들웨어로 통일. RLS 기본/2차를 하나로 확정. Phase 0 스키마에 cohort/account_linking/audit_log 포함.
### F-31. [데이터·윤리] RAG 4종 용도가 단일 pgvector 1024d로 뭉뚱그려짐 — BGE-M3 멀티벡터/sparse/맥락 컬럼 부재
- **카테고리:** 기술결함
- **병합 출처:** integration F12
- **근거:** §3.6은 RAG 3종 "서로 다른 RAG" + BGE-M3 하이브리드(dense+sparse+ColBERT) 명시하나, §3.2는 `rag_chunks(embedding vector(1024))` 단일 dense 컬럼. sparse·ColBERT·Contextual 맥락문장·리랭커 입력 담을 없음. 3AI §4.3은 3인덱스+graphify MCP로 다름.
- **수정방향:** `rag_chunks` `index_kind`·`sparse_vec`·`context_prefix`·`colbert_vecs` 추가. 하이브리드 검색 SQL 계약+리랭커 경계 §3.6 명시. graphify-lambda vs pgvector 택일( 다면 동기화 계약).
---
## 🟡 MINOR 등급
### F-32. [데이터·윤리] KPI 임계치 문서 간 불일치 (κ/ICC ≥0.80 vs ≥0.6/0.75)
- **출처:** data m1. 설계서 §1.2 "≥0.80(39편 메타리뷰)" vs §3.37 "현실치 0.6/0.75". **수정:** 0.6/0.75로 통일 또는 "외부벤치 목표 0.80 vs 파일럿 현실 0.6" 명시 구분.
### F-33. [데이터·윤리] "환각률 ≤5%(목표 ≤1%)" 측정 정의 부재
- **출처:** data m2. 판정 주체가 LLM-judge면 F-06(judge 타당도 미검증) 순환. **수정:** 환각 판정 인간 검수 고정 또는 judge 환각판정 정확도 별도 보고.
### F-34. [데이터·윤리] CCD core_belief 3유형 중 unlovable 누락 + P1에 2개 동시 부여
- **출처:** data m3. Patient-Ψ 원설계는 단일 우세 신념. **수정:** 우세 1개+보조 구조화, 3유형 커버리지 페르소나 백로그 반영.
### F-35. [데이터·윤리/원래요구위반] "재귀적 학습" 메커니즘 미정의 — 축적 ≠ 학습
- **출처:** data m4. JSONL export까지만, 데이터로 무엇을 fine-tune/few-shot 업데이트하는지 루프 닫힘점 없음. **원래요구위반:** 요구5 "재귀적으로 AI가 학습" 구현체 부재. **수정:** "골든셋 누적few-shot 자동갱신평가 프롬프트 업데이트" 명시 루프로 정의(fine-tuning 여부 1차 범위 결정).
### F-36. [기술결함] 프롬프트 캐싱 "59~70% 절감"이 Opus 4.8 최소 프리픽스 4096토큰 미달 시 silent miss
- **출처:** security m1. **수정:** `usage.cache_read_input_tokens` 히트 검증, 페르소나+RAG 프리픽스가 4096토큰 넘는지 확인, silent invalidator(타임스탬프) 추적. 측정 절감률 보고(`feedback_measure_before_report`).
### F-37. [기술결함/데이터·윤리] secrets git-ignore만으로 미성년 데이터 키관리 불충분 — 가명↔원본 매핑 격리 미명세
- **출처:** security m2. **수정:** 키는 secrets manager/OS 키체인, 가명 매핑 테이블은 암호화 DB+2인 승인 명세화. 운영 계정류는 정해진 위치만(`feedback_obsidian_secrets_folder`), 폴더 임의 생성 금지.
### F-38. [기술결함] 위기분류 "수련생 실제위기 vs 페르소나 연기" 판정 계약 미정의 (음성 화자라벨 경계케이스)
- **출처:** integration F11. 화자=counselor의 모든 위기발화를 실제위기로 에스컬레이션하면 false-positive로 시뮬레이션 중단 남발. **수정:** 입력계약 `{speaker, stage, text_masked, is_roleplay_context}→{risk_level, escalate}`, "본인+1인칭 현재시제+시뮬레이션 메타밖" 결정론 우선. Phase 2 DoD에 false-positive 케이스 포함.
### F-39. [기술결함] `--bare` 재현성 vs 모드A 정액 트레이드오프가 평가루프 신뢰도에 미치는 영향 미정량
- **출처:** engine F-8. 평가루프(③deep) `--bare` 필수라면서 정액 모드(비-bare) 글로벌 CLAUDE.md/hooks 로드로 재현성 위협. **수정:** deep만 API키+`--bare`(또는 Messages API) 재현성, 내담자는 정액. 역할별 인증/플래그 분기 명시.
### F-40. [기술결함/원래요구위반] 단일호스트 모놀리식 vs 요구12 "스케일업" 정의 갭
- **출처:** security m3. K8s 금지는 20주에 합리적. **수정:** 1차 설계 유지, "스케일업=클라우드 VM 이전+compose replicas" 윤찬과 정의 합의. K8s는 2차 백로그.
---
## 부록. 자기반증으로 폐기한 공격 (투명성)
렌즈가 약하다고 판단해 버린 결함 Timescale 미도입(PG16으로 충분), pgvector RAG(벡터DB 미지정), 모노레포 과설계(요구10 대비 정당), DSM 진단명 비노출(학술적으로 옳음), 0-5 vs CTRS 0-6(분리운영 방어됨), React 19 미성숙(2026 안정화), Presidio 한국어 NER(M5로 통합), s2s 탈락이 데이터 렌즈상 요구위반(transcript 보존이 재귀학습엔 정당 *결정권 월권* F-08로 살림), BGE-M3 rag-memory 충돌(역할분리 명시), Docker 6컨테이너 과다(20명 규모 합리적).
---
## 종합 판정
| 카테고리 | 결함 | 핵심 ID |
|---|---|---|
| **원래요구위반** | 10 | F-01·02·03·08·09·10·11·12·28·35·40 |
| **기술결함** | 14 | F-07·13·14·15·19·20·21·29·30·31·36·38·39·40 |
| **오케스트레이션·구현능력** | 5 | F-11·16·17·18·27·28 |
| **데이터·윤리** | 12 | F-03·04·05·06·20·22·23·24·25·26·31·32~35·37 |
**BLOCKER 7건:** F-01(엔진 바꿔치기) · F-02(음성 격하) · F-03(마스킹 우회) · F-04(n=1 골든셋) · F-05(미성년 재귀학습 동의) · F-06(타당도 미검증 평가) · F-07(음성 WSS 토폴로지 누락)
**최우선 시정 3건:**
1. **F-01 — 엔진 기본값을 claude -p로 복원.** 윤찬 요구의 심장. 비용/동시성/rate limit 변명 약함(정액 한계비용 0, 프로세스 +`--input-format stream-json` 상주로 동시성 해결, 20명 규모 근거 빈약). 마스터플랜과 하위 설계서 2종의 엔진 결정을 **하나로 통일**.
2. **F-04+F-05+F-06 결합 — 시스템 전체가 동의 미확보 미성년 자살사례 1건 위에 서 있고, 타당도 미검증 평가 AI가 수련생을 먼저 가르친 뒤 사후에 신뢰도를 잰다.** "골든셋·빡세게·적대적 검증 완료" 빈약한 데이터 토대와 순환 검증을 학술 외관으로 덮음.
3. **F-11 — IRB 본문 전수 정리.** 헤더만 고치고 본문(Phase 게이트·액션·체크리스트) IRB 의존성 방치 = 부분 수정 누락.
**메타 결론:** 4개 하위 설계서가 서로의 결론을 부정하는 상태(엔진·음성전송·스키마·권한모델 모두 모순) "단일 기준 문서(SoT)"라는 전제 자체가 아직 지켜졌다. `feedback_proper_backlog_planning` 원칙상 통합 SoT 재정렬이 선행돼야 한다.