chore: Vignette 모노레포 초기 스캐폴드 + 설계 문서 이관

- apps/web(React) · apps/api(FastAPI) · infra(Docker) · docs(설계 SoT)
- 마스터플랜·적대검증·메모리설계·디자인컨셉 docs 이관
- 미성년 사례데이터는 .gitignore로 제외(개인정보 보호)
This commit is contained in:
Yun Chan 2026-06-25 21:16:45 +09:00
commit 709baadd01
12 changed files with 3087 additions and 0 deletions

View file

@ -0,0 +1,335 @@
# MASTERPLAN REVISIONS — BLUE TEAM 재설계 (윤찬 원래요구 100% 충족판)
> 작성 2026-06-25 · BLUE TEAM(재설계자) · 대상 결함: `REDTEAM_FINDINGS.md` F-01~F-40
> **원본 마스터플랜은 보존.** 이 문서는 **변경점(패치) 전용**이다. 적용 시 `HANSHIN_AI_PLATFORM_MASTERPLAN.md`의 해당 절을 본 문서로 덮어쓴다.
> **재설계 원칙: 타협으로 결함을 덮지 않는다.** "claude -p 못 쓰니 API로" 같은 요구 깎기는 금지. claude -p를 **1급 엔진으로 실제 돌리는** 아키텍처를 설계했다.
---
## ⚡ 0. 핵심 결정 역전 요약 (원본 §0 표를 이걸로 교체)
RED TEAM이 BLOCKER로 지목한 "요구 깎기"를 전부 되돌린다. **검증 근거는 실제 CLI v2.1.191 직접 실행**(추측 아님, `feedback_measure_before_report` 준수).
| 영역 | 원본(깎인) 결정 | **BLUE TEAM 복원 결정** | 검증/근거 |
|---|---|---|---|
| **AI 엔진** | 기본=Messages API, claude -p=옵션 | **기본=로컬 `claude -p` 상주 풀(resident pool).** Messages API는 **가용성 폴백 전용**(claude -p 다운 시에만 자동 전환) | `--input-format stream-json`(="realtime streaming input") 실재 확인 → 1턴종료 모델 극복, 상주 멀티턴 가능 |
| **음성** | P1·Phase 2로 격하, Phase 1 음성 0 | **Phase 1 DoD에 "1페르소나·1보이스 캐스케이드 음성 왕복 1턴" 포함.** "무조건"을 일정 첫 외부시연부터 증명 | OpenAI gpt-4o-mini-tts + Deepgram, WSS 경로 1급화 |
| **음성 s2s** | "1차 탈락" 단독 확정 | **"캐스케이드 1차 / s2s 2차 PoC 옵션".** 탈락 근거를 transcript 보존 단일 사유로 정리, 결정권은 윤찬 | OpenAI `input_audio_transcription` 네이티브 존재 → "transcript 없음"은 허수아비였음 |
| **자유연습** | 서버단 하드 차단 | **기본 ON + 피드백 권장 배지 + 교수자 토글.** 차단은 미동의/미성년만(개인정보 사안) | `feedback_risk_user_decides`: 위험은 알리되 통제권은 사용자 |
| **IRB** | 헤더만 패치, 본문 잔존 | **본문 전수 정리.** "IRB 신청/승인" 전 게이트 삭제, "교육용 파일럿"으로 통일 | 요구16 |
| **fast-loop 엔진** | 외부 Haiku/Solar API 기본 | **로컬 상주 분류기(NAS) 또는 상주 Haiku claude -p 기본.** 외부 API는 폴백 | 요구3 데이터주권 |
| **마스킹 게이트** | claude -p 우회 가능 | **claude -p 경로도 Presidio 선통과 강제.** 어댑터가 마스킹 후에만 stdin 주입 | 요구5/16 |
| **음성 전송** | 토폴로지에서 누락 | **`voice.chanpaca.net` WSS 경로 1급 추가** | 요구7+요구4 E2E |
> **메타 선언:** 9개 하위 설계서가 엔진·음성전송·스키마·권한모델에서 서로 모순(RED TEAM 메타결론)이었다. 본 문서가 **단일 SoT 재정렬**을 수행한다. 적용 후 모든 하위 설계서의 엔진 결정은 본 §1로, 권한 모델은 본 §5로, 스키마는 본 §3으로 통일한다.
---
## 1. 엔진 재설계 — claude -p 로컬 상주 풀을 1급으로 실제 구동 [F-01·F-12·F-13·F-14·F-15·F-29·F-39 해소]
### 1.1 핵심 돌파구: `--input-format stream-json` 상주 프로세스 (F-13 자기반박 해소)
RED TEAM·하위설계서 §6.3이 막혔던 지점 = "claude -p는 1턴 후 종료라 warm pool 불가 → SDK/API로 가야 함". **이 전제가 틀렸다.** CLI v2.1.191 실측:
```
--input-format <format> "text"(default) | "stream-json" (realtime streaming input)
--replay-user-messages stream-json in+out 조합에서 user 메시지 ack 재방출
```
**단일 claude -p 프로세스를 띄워놓고 stdin으로 턴마다 JSON 메시지를 주입**하는 양방향 멀티턴 모드가 네이티브로 존재한다. 콜드스타트를 **회기당 1회**(프로세스 기동 시)로 압축한다. 매 발화 콜드스타트(수 초)가 TTFT에 얹히는 문제 소멸.
```
[engine-pool 컨테이너] (FastAPI와 분리된 별도 프로세스 매니저)
┌─ claude -p #1 (resident, --input-format stream-json --output-format stream-json)
│ stdin ◄── {"type":"user","message":{...},"session_id":...} (턴마다 주입)
│ stdout ──► stream-json NDJSON (assistant delta, result, total_cost_usd)
├─ claude -p #2 (resident) ← 내담자 AI 전용 풀
├─ claude -p #3 (resident) ← deep-loop 평가 전용 풀
└─ ... (MAX_RESIDENT 만큼, 회기 수요에 따라 동적 스폰/회수)
```
### 1.2 정확한 호출 형태 (실CLI 검증 — 깨진 플래그 전부 교체) [F-14 해소]
원본 3AI §2.2 템플릿은 **존재하지 않는 플래그**를 썼다. 교체:
| 원본(깨짐) | 실CLI v2.1.191 | 교체 |
|---|---|---|
| `--max-turns 1` (없음) | 존재 안 함 | **제거.** 도구 미사용 시 단일응답 종료가 기본. 폭주 통제는 `--max-budget-usd`(실재) |
| `--append-system-prompt-file` (메인 help 부재) | `--append-system-prompt <prompt>`(문자열)만 확인 | **전체 프롬프트 문자열 주입** 또는 `--settings`로. file 변형은 윤찬 PC 실증 후에만 채택 |
| `--bare` (정액 모드 기본) | `--bare`**OAuth/keychain 절대 미독**(API키 강제) | **정액(모드 A)에서 `--bare` 제거.** 재현성은 격리 `CLAUDE_CONFIG_DIR`+`--settings`(hooks off)+`--strict-mcp-config`로 |
**모드 A (정액·기본 — 윤찬 요구3의 심장):**
```bash
# 환경: claude setup-token OAuth 토큰 발급된 전용 HOME/CLAUDE_CONFIG_DIR
CLAUDE_CONFIG_DIR=/srv/sim/_cfg_client \
claude -p \
--model claude-opus-4-8 \
--append-system-prompt "$(cat ./prompts/client_persona.txt)" \
--input-format stream-json --output-format stream-json \
--include-partial-messages --verbose \
--strict-mcp-config --mcp-config ./mcp/rag.json \
--allowedTools "mcp__counseling_rag__search" \
--settings '{"hooks":{},"disableAllHooks":true}' \
--max-budget-usd 5 \
--fallback-model "claude-sonnet-4-6"
# stdin: 턴마다 {"type":"user",...} 주입 (상주)
```
- `--bare` **없음** → OAuth 정액 정상 작동. Max ×3 구독 한도 내 **한계비용 0**(종량제 위험 $1,800은 API키 경로 위험이지 정액 위험 아님 — F-01 논리오류 교정).
- 격리 `CLAUDE_CONFIG_DIR` + `--strict-mcp-config` + `disableAllHooks` → 글로벌 CLAUDE.md/hooks/디코MCP 오염 차단(=`--bare`가 주던 재현성을 정액 유지하며 확보).
- `--max-budget-usd 5` → 회기당 비용 상한(폭주 자동 중단). `--max-turns` 없이도 통제.
- `--fallback-model` → overload/unavailable 시 CLI 자체가 Sonnet으로 폴백(가용성 1차 안전망).
**모드 B (가용성 폴백 — 1급 아님, F-19 안전망):** claude -p 프로세스 자체가 죽거나(OOM/rate-limit/토큰만료) 헬스체크 실패 시에만 어댑터가 **Anthropic Messages API**로 자동 전환. 평시엔 안 씀.
### 1.3 동시성·큐·과금통제 (F-13 부하 / F-29 비용) — 실측 게이트 신설
```
회기 라우터 → 회기별 직렬 큐(같은 session_id 턴 순서보장, asyncio.Lock)
→ 전역 Semaphore(MAX_RESIDENT, 초기 4~6, 부하테스트로 확정)
→ 상주 풀에서 idle 프로세스 할당 (없으면 스폰 or 백프레셔 큐)
```
- **상주 풀 정책:** 회기 시작 시 ②내담자용 1 + ③deep용 1 프로세스 점유, 회기 종료 시 회수. ③fast는 로컬 분류기(별도 경량 풀, claude -p 아님).
- **과금통제 3중:** ①정액이라 한계비용 0(평시) ②`--max-budget-usd` 회기 상한 ③`total_cost_usd`(stream-json result 이벤트)를 `turns.cost_usd`에 실적재 → 폴백(모드 B) 비율·실비용 실시간 모니터, 임계 초과 시 디코 알림.
- **F-13 게이트 (Phase 1 DoD 신설):** "상주 claude -p TTFT p50/p95 **실측** + 동시 4회기 부하에서 열화곡선·피크 RSS·OOM 0건". **실측 전 400~900ms를 계획수치로 쓰지 않는다**(`feedback_measure_before_report`). 측정은 윤찬 PC에서 1회 실증 후 "검증됨" 표기.
### 1.4 fast-loop 데이터주권 복원 [F-12 해소]
- 매 발화 도는 fast-loop 기본 = **로컬 상주 분류기(NAS, 1B급 또는 상주 Haiku claude -p)**. 외부 Haiku/Solar API는 폴백.
- 어느 경로든 `turns.llm_provider`에 적재 → "claude/로컬 비중" 측정 가능. 외부 유지 시 윤찬 승인 + 마스킹 지연을 §6 예산표 반영.
### 1.5 어댑터 정규화 계약 [F-15 해소]
- `LLMEngine` 인터페이스: 정규화 이벤트 스키마(`delta.text` / `result` / `cost`) + **정규화 cost 규약**(정액=토큰×참조단가 shadow cost, 종량제=실 total_cost_usd). 두 경로 cost 의미 통일 → 재귀학습·텔레메트리 일관성(요구5).
- **contract test DoD화:** 동일 입력 → claude_cli 경로와 messages_api 경로가 동일 정규화 출력. Phase 0~1에 둘 다 구현.
### 1.6 역할별 인증/플래그 분기 [F-39 해소]
| AI | 엔진 | 인증/모드 |
|---|---|---|
| ②내담자(품질 생명) | Opus 상주 claude -p | 모드 A 정액 |
| ③deep-loop 평가(재현성) | Opus 상주 claude -p, 격리 cfg | 모드 A 정액 + `--settings` 고정(재현성) |
| ③fast-loop | 로컬 분류기/상주 Haiku | 로컬 |
| (전 경로 폴백) | Messages API | 모드 B (claude -p 다운 시만) |
---
## 2. 음성 재설계 — "무조건 + 멀티보이스 + 페르소나" 일정 첫날부터 증명 [F-02·F-07·F-08 해소]
### 2.1 Phase 1에 음성 PoC 진입 (F-02 해소)
- **Phase 1 완료기준에 추가:** "P1 1페르소나·1보이스(OpenAI gpt-4o-mini-tts) 캐스케이드 음성 왕복 **1턴 PoC**가 chanpaca.net에서 동작". 텍스트 완주와 **별도 독립 트랙**(소유파일 분리)으로 얇게라도 "무조건"을 일정에 박는다.
- Phase 2에서 음성을 IRB·3역할과 **분리 독립 트랙**으로(원본은 한 Phase에 뭉쳐 슬립 시 음성 증발 — F-27과 함께 해소).
### 2.2 음성 전송계층 WSS 1급화 (F-07 해소) — 토폴로지에 명시 추가
원본 §1.1 토폴로지에 음성이 통째 없었다. **추가:**
```
[교수 브라우저] ─ getUserMedia/AudioWorklet PCM16 24kHz
├─ https://chanpaca.net (정적·일반 API) ← Cloudflare named tunnel
├─ https://stream.chanpaca.net (SSE 텍스트) ← §5에서 단일터널 통합 재검토
└─ wss://voice.chanpaca.net (음성 양방향 PCM) ← WSS 전용 경로 [신규 1급]
[Caddy] WS upgrade 통과 + 버퍼링 off + proxy_read_timeout 3600s
[voice-gw (FastAPI WebSocket)]
├─ ① Deepgram Nova streaming STT → interim/final transcript(+화자,ts)
├─ ② EOT(semantic, median<300ms, 상담튜닝 침묵임계 1.2~2.0s)
├─ ③ 입력 가드레일(한국어 위기분류, 화자=수련생 실제위기 vs 페르소나 연기 분기)
├─ ④ engine-pool(상주 claude -p) 추론 ← §1 엔진과 동일 풀 공유
├─ ⑤ 출력 가드레일
└─ ⑥ OpenAI gpt-4o-mini-tts(voice_id 추상화) → 오디오청크 WSS down
```
- **Phase 1 트랙 C DoD화:** "50분 WSS 양방향 스트림 끊김 실측"을 SSE 테스트와 함께. Cloudflare 터널이 WSS 바이너리를 못 받으면 → voice 전용 Tailscale Funnel 또는 cloudflared WS 지원 경로로 분리(전송 라우팅 표를 단일 계약으로 고정).
### 2.3 멀티보이스·페르소나 (요구7 완전충족)
- **voice_id provider-agnostic 추상화**: `voice_id → {provider, params}`. OpenAI TTS 13보이스 + `instructions` prosody 스티어링이 1차. 한국어 자연성 미달 보이스는 Higgs(127.0.0.1:9881)/MeloTTS 로컬 폴백(이미 vault 보유 자산).
- **보이스=상태머신 함수**: 매 턴 `{voice, instructions, speed, stage, resistance, emotion}` 주입 → 단계별 음성 변조(라포기 닫힘 → 개입기 미세개방). 페르소나별 다른 목소리 = 요구7 "여러 목소리+페르소나" 충족.
- **음성 paralinguistic 컬럼**(F-21): 침묵길이/말속도/바지인을 수치 메타로 turn 로그 적재(§3 스키마 선반영).
### 2.4 s2s 결정권 복원 (F-08 해소)
- "s2s 탈락"(단독확정) → **"s2s 2차 PoC 옵션 유지"**로 표현 격상. 탈락 근거를 **transcript 보존 단일 사유**로 재정리(OpenAI `input_audio_transcription` 네이티브 존재 → "transcript 없음" 허수아비 폐기).
- **윤찬 결정사항으로 명시 보고**: "캐스케이드 1차 / s2s는 가상내담자 1캐릭터 몰입 2차 PoC". 람다 단독 탈락 확정 철회(월권 시정).
---
## 3. 데이터·스키마·학술 재설계 [F-03·F-04·F-05·F-06·F-21·F-22·F-23·F-24·F-25·F-26·F-31·F-35 해소]
### 3.1 마스킹 게이트 우회 차단 (F-03 — BLOCKER)
- **엔진 어댑터가 claude_cli 경로일 때도 프롬프트를 Presidio 선통과 후 stdin 주입.** claude -p가 backend 미들웨어를 우회해 미성년 원문을 Anthropic에 직송하던 구멍 봉쇄.
- §1.1 문구 정정: "데이터는 로컬 미이탈" → **"마스킹된(가명처리) 텍스트만 Anthropic 포함 외부로 전송"**. 공문/처리방침에 "가명처리본 해외(Anthropic) 전송" 명시. 민감구간은 Solar/HyperCLOVA 국내 라우팅 우선.
### 3.2 n=1 데이터 토대 정직화 + 수급을 블로킹 의존성 격상 (F-04 — BLOCKER)
- "골든셋" → **"시드 1례(seed exemplar), 신뢰도 측정 불가"**로 정직 표기. n=1 빈약함을 **리스크 레지스터에 신규 등록**(원본 누락).
- Phase 0 "골든셋 50발화"를 **"한신대 추가 축어록 N건 수급"을 블로킹 의존성으로 격상** → §8 공문 액션에 **추가**(원본 누락 항목).
- **train/test 누수 차단:** 0615을 페르소나 시드(②용)와 평가 정답셋(③용)으로 **분리**. 같은 데이터 이중사용 금지(F-26 순환의존 동시 해소).
### 3.3 미성년·자살사례 재귀학습 동의 (F-05 — BLOCKER)
- 법정대리인 동의서에 **별도 동의항목 분리**: "AI 학습데이터 2차 가공 · DB 영구축적 · 파생모델 배포". **동의 전 0615 `turns.text` 적재 금지를 Phase 0 hard gate**로.
- 자살사고 미성년 발화는 **합성·환언된 CCD 스펙만** 학습원천. 원문은 audit 보존용 격리(plain DB 미적재). → §3.3 "원본 미적재" 주장과 taxonomy §8 "원문 125턴 적재"의 자기모순 해소.
- "IRB 면제"는 **수련생 실험 면제**이지 **미성년 사례데이터 활용 면제 아님** 명문화.
### 3.4 평가 AI 타당도 선검증 (F-06 — BLOCKER, 오학습 순환 차단)
- 평가 AI 타당도를 **수련생 노출 전** 별도 검증셋(F-04 수급 전제)에서 LLM-judge κ 확보. 미달 차원은 학습자에 **점수 비노출(코칭 텍스트만)**.
- 초기 deep-loop는 단정 채점 금지 → **"관찰" 프레이밍**("이 발화는 폐쇄형이었고, 개방형으로 바꾸면…"). 거짓양성률 정량 임계 설정 + 파일럿 1차 지표로 승격.
- **순환 차단 원리:** 타당도 보증이 사용 시점보다 늦지 않게 — 검증 → 노출 순서 강제.
### 3.5 스키마 단일 SoT 통합 (F-21·F-31)
원본 §3.2 스키마에 음성·RAG 컬럼 누락 → **선반영**:
```sql
-- turns 확장 (음성 메타, nullable 선반영 → Phase 2 재마이그레이션 폭탄 방지)
ALTER ... turns ADD audio_ref TEXT, silence_ms INT, speech_rate REAL, barge_in BOOL;
-- 또는 turn_paralinguistic(turn_id PK FK, ...) 1:1 확장
voice_persona_map(persona_id, voice_id, provider, params JSONB)
-- rag_chunks 하이브리드(BGE-M3 멀티벡터) 선반영
rag_chunks(id, source, index_kind, embedding vector(1024),
sparse_vec JSONB, context_prefix TEXT, colbert_vecs ... , text)
```
- 하이브리드 검색 SQL 계약 + 리랭커(BGE-reranker-v2-m3) 경계를 §3.6에 명시. graphify-lambda vs pgvector는 **pgvector 1차 단일**(graphify는 상담이론 교차개념 맵 2차).
### 3.6 학술 엄밀성 보강 (F-22·F-23·F-24·F-25·F-35)
- **F-22 DSM-5:** `ideation_stage 1~5 ↔ C-SSRS 정식축 매핑표` + P1~P3 `DSM-5 진단기준 ↔ 행동증거 매트릭스` 추가. "진단 비노출"과 "진단학적 엄밀"은 양립(내부 파라미터).
- **F-23 슈퍼바이저 편향:** 1인·1회기 논평을 "모범 코퍼스" 일반화 철회 → **few-shot/검증 참조로만**. AI 피드백 앵커는 EPITOME/CTRS 루브릭. "(현장 특이)" 항목 학습신호 제외. 슈퍼바이저 다인 확보 전 1인 편향 가중치 다운.
- **F-24 인용 검증:** 신청서·공문 제출 **전** 모든 arXiv ID 실재 확인, preprint vs peer-reviewed 구분, 핵심 수치(d=0.72/ICC 0.853/77.2%) 원문 캡처. 미확인은 "preprint, 미검증" 라벨.
- **F-25 재식별:** 사례 메타 재식별 위험평가(motivated intruder test), 학년/나이 범주화, 호소문제 일반화. 학습원천=합성변형(F-05 연동).
- **F-35 재귀학습 루프 닫기:** "축적 ≠ 학습" → **명시 루프 정의**: `골든셋 누적 → few-shot 풀 자동갱신 → 평가/페르소나 프롬프트 업데이트`. fine-tuning 여부는 윤찬 1차 범위 결정(§잔여결정).
---
## 4. IRB 본문 전수 정리 [F-11 해소]
원본이 헤더만 패치하고 본문에 IRB 의존성 잔존. **전수 삭제/치환:**
- Phase 0 작업 "IRB 프로토콜 초안" / 완료기준 "IRB 신청서 제출" → **삭제**.
- Phase 3 의존성 "+IRB 승인" → **삭제**. "20명 IRB 파일럿" → **"20명 교육용 파일럿"**.
- §8 액션 #2 "IRB 프로토콜 제출 — 승인 리드타임이 Phase 3 게이트" → **삭제**.
- §7 IRB 체크리스트 → **미성년 활용동의 + 개인정보 처리방침 + PIPC/생명윤리법 가명처리만 잔존**, IRB 심의 항목 전부 제거.
- 단 §3.3/§9 안전 가드레일·minimal risk 설계는 **윤리 설계로 유지**(IRB 절차와 무관한 안전 사안).
---
## 5. 권한·보안 재설계 [F-19·F-20·F-28·F-30·F-37·F-38·F-40 해소]
### 5.1 visible_to[] vs RBAC×cohort 레이어 분리 통일 (F-30)
- `visible_to[]`(**AI 정보비대칭**)와 RBAC×cohort(**인간 권한**)는 **다른 레이어**로 명시 분리. 인간이 turn 읽을 때 **두 게이트 AND**를 단일 enforcement 미들웨어로 통일.
- RLS "기본/2차" 모순 → **RLS 기본강제로 확정**(앱 게이트가 1차, RLS가 DB레벨 방어선). Phase 0 스키마에 `cohort` / `account_linking` / `audit_log` 포함(원본 누락).
- 요구8(3페이지: 관리자/학습자/교수자) 권한격리 강제 메커니즘 일관화.
### 5.2 SSE/WSS 무인증 노출 + 쿠키 붕괴 차단 (F-20 — IDOR 위험)
- SSE도 **단일 도메인 + Cloudflare 단일 터널**에서 **먼저 실측**(heartbeat + `no-transform` + flush -1). 끊길 때만 분리.
- 분리 불가피 시 stream/voice 경로도 **BFF 경유 + short-lived signed token**(쿠키 아닌 header/query, 세션당 1회·단명). `__Host-` 쿠키가 다른 호스트에 미전송되는 구조적 붕괴 회피.
- WSS(음성)·SSE(텍스트)를 **같은 전송 추상화**로 통합 검토(노출면 최소화). `reference_cloudflared_external_share` 멀티tailnet 함정 주의.
### 5.3 가용성 SPOF 해소 (F-19) — 요구3+요구4 양립
- (a) 엔진 PC ↔ NAS DB **다른 물리 장애도메인** 분리.
- (b) **교수 테스트 예약 슬롯제** + 직전 헬스체크(PC alive · 상주풀 워밍 · 터널 up) 후 링크 발송.
- (c) **watchdog**(claude/cloudflared/docker 자동 재기동) + 외부 모니터 → 디코 알림. `reference_codex_node_memory_leak` 전례(좀비 node OOM) 대응 1GB+ 프로세스 reaping.
- (d) claude -p 다운 시에만 Messages API 자동 폴백(=§1.2 모드 B, 가용성 안전망). PC 절전/윈도우업데이트 방지(`.ps1` ASCII 함정 주의 — `reference_ps1_ascii_only`).
### 5.4 SSO 블로커 게이트화 (F-28)
- 공문 질의를 **Phase 0 게이트 격상**(IRB 면제로 SSO가 최장 리드타임 블로커). Google OIDC 단독 1차 진행 + Authlib provider 뒤 **SAML SP 어댑터 스캐폴드 선반영**.
- 용어 분리 명시: **(사용자 로그인 OAuth 2.1)** vs **(엔진 Max OAuth 토큰)** 혼용 금지.
### 5.5 잔여 보안 (F-37·F-38·F-40)
- **F-37 키관리:** secrets git-ignore만으론 불충분 → 키는 OS 키체인/secrets manager, **가명↔원본 매핑 테이블은 암호화 DB + 2인 승인**. 운영계정류는 정해진 위치만(`feedback_obsidian_secrets_folder`), 새 폴더 임의생성 금지.
- **F-38 위기분류 계약:** 입력계약 `{speaker, stage, text_masked, is_roleplay_context} → {risk_level, escalate}`. "본인+1인칭 현재시제+시뮬레이션 메타밖" 결정론 룰 우선(페르소나 연기 false-positive 남발 차단). Phase 2 DoD에 false-positive 케이스.
- **F-40 스케일업:** K8s 금지(20주 합리). "스케일업 = 클라우드 VM 이전 + compose replicas"로 윤찬 정의 합의. K8s 2차 백로그.
---
## 6. 오케스트레이션·일정 재설계 [F-16·F-17·F-18·F-27 해소] — 람다 실구현 작업분해 + 검증게이트
### 6.1 RACI — 소유주체 매핑 (F-16: "기존 풀스택팀 5글자" 해소)
원본은 트랙만 나누고 소유주체 0. **명시:**
| 트랙 | 소유 | 람다 역할 | 디렉토리 경계 | 인터페이스 계약 동결 |
|---|---|---|---|---|
| A1 엔진풀(상주 claude -p) | spawn dev세션 #1 | 계약정의+E2E검증 | `backend/engine/` | LLMEngine 정규화 스키마(Phase 0말) |
| A2 상태머신·가드레일 | spawn dev세션 #2 | 계약정의+검증 | `backend/sm/`,`backend/safety/` | TurnLog/SessionState 스키마(Phase 0말) |
| B 프론트(React19·SSE·음성UI) | spawn dev세션 #3 | 검증 | `apps/web/` | SSE/WSS 이벤트 스키마(Phase 0말) |
| C 인프라(터널·Caddy·Docker·DB) | 람다 직접(인프라 영역) | 직접 | `infra/`,`docker-compose.yml` | — |
| D 데이터(라벨링·검수·κ) | 크론+영속워크플로우 | 오케스트레이션 | `ds/` | annotation 스키마(Phase 0말) |
- 람다(메인)는 **인프라·계약정의·팀간 중계·완료기준 검증**에 집중(`feedback_team_lead_active_supervision`). 비대 트랙 A를 A1/A2로 분할 → 람다 직접제작 회귀 차단.
- `lambda-spawn-dev-session` 스킬로 PowerShell + `claude --dangerously-skip-permissions` + windows-mcp 세션 부려 위임. 산발 task 금지, 본 문서가 단일 로드맵(`feedback_proper_backlog_planning`).
### 6.2 검증 프로토콜 — 모든 DoD에 "누가/어떻게" 명시 (F-17 — 완료보고 불신 원칙)
원본 DoD는 전부 결과서술("교수님이 상담→피드백 수신"). **검증 외주 금지**(`feedback_verify_actual_interaction`). 각 DoD에 **람다 직접 실동작 검증** 부착:
| Phase | 결과 DoD | **람다 검증 프로토콜(신규)** |
|---|---|---|
| P1 텍스트루프 | 상담→피드백 완주 | 람다가 Playwriter/windows-mcp로 **실제 로그인 → P1 상담 완주 → 피드백 수신 재현**, turn DB쿼리로 cost 적재 확인 |
| P1 저항엔진 | 공감↑/조언점프↓ | **공감 5턴 vs 조언 5턴 입력 → openness 곡선 DB쿼리 정량 대조** 스크린샷 |
| P1 엔진풀 | 상주 claude -p 동작 | **TTFT p50/p95 실측 로그 + 동시4회기 부하 RSS/OOM 0** 캡처(§1.3 게이트) |
| P1 음성PoC | 음성 왕복 1턴 | 람다가 **실제 마이크/오디오 왕복 1턴 + WSS 50분 끊김 실측** |
| P2 권한격리 | 타인기록 차단 | **타인 session_id 직접입력 → 403 스크린샷**(IDOR 음성검증) |
| P2 안전 | 위기→교수알림 | **위기발화 주입 → 에스컬레이션+알림 end-to-end 재현** |
| 각 Phase말 | — | **통합게이트: 람다 E2E 1회 재현** 후에만 윤찬 보고("완료" 보고 신뢰 금지) |
- subagent 물리적 불가 작업(50분 SSE/WSS, 실시간 음성 레이턴시, OAuth 콜백)은 **백그라운드 Bash+Monitor / 실기기 / Playwriter**로 배정(원본 미배정 해소).
### 6.3 장기·상태유지 작업 오케스트레이션 (F-18)
- 라벨링·검수·κ누적은 수일~수주 인간-루프 → **DB/파일 영속 작업으로 재정의**. 람다는 **CronCreate + 단계 재개 워크플로우**로 오케스트레이션. `ds` 스키마에 체크포인트 저장, 다음 세션 이어받기(stateless 한 호출로 끌고 가려던 설계 결함 해소).
### 6.4 일정 재분할 (F-27: 7주에 음성+3역할+페르소나+재귀 동시압축 해소)
- **Phase 2 분할:** 2a(3역할+OAuth BFF+페르소나, 9~13주) / 2b(음성 캐스케이드 1페르소나, 13~17주).
- 재귀학습 IAA·자살분류기 정밀화는 **Phase 3 이연**. 음성 M-단계(설계서 §8)와 Phase 주차를 **단일 간트로 통합**(음성 단독 20주를 7주에 욱여넣던 충돌 해소).
- "기존 풀스택팀(JS 추정)"의 FastAPI/asyncio/Presidio/pgvector/Deepgram WS 학습곡선을 일정에 반영(2b를 별도 트랙·여유 배치).
---
## 7. 결함ID → 해소방안 매핑 (전수 추적표)
| ID | 심각도 | 해소 위치 | 한 줄 해소 |
|---|---|---|---|
| F-01 | BLOCKER | §0·§1.2 | 기본엔진 claude -p 상주풀 복원, Messages API는 폴백 강등 |
| F-02 | BLOCKER | §2.1 | Phase 1 DoD에 음성 왕복 1턴 PoC 포함 |
| F-03 | BLOCKER | §3.1 | claude -p 경로도 Presidio 선통과 강제, 우회 봉쇄 |
| F-04 | BLOCKER | §3.2 | n=1 정직표기 + 축어록 수급 블로킹 의존성 격상 |
| F-05 | BLOCKER | §3.3 | 미성년 재귀학습 별도 동의항목 + 동의 전 적재 금지 hard gate |
| F-06 | BLOCKER | §3.4 | 평가 AI 타당도 수련생 노출 전 선검증, 미달 비노출 |
| F-07 | BLOCKER | §2.2 | voice.chanpaca.net WSS 경로 1급 추가 + 50분 실측 DoD |
| F-08 | MAJOR | §2.4 | s2s "탈락"→"2차 PoC 옵션", 결정권 윤찬 |
| F-09 | MAJOR | §3.4 | "판단 지속(deep-loop 백그라운드), 제시만 회기말" 분리 |
| F-10 | MAJOR | §0 | 자유연습 하드차단 제거 → 기본ON+권장배지+교수토글 |
| F-11 | MAJOR | §4 | IRB 본문 전수 삭제/치환 |
| F-12 | MAJOR | §1.4 | fast-loop 로컬 상주분류기 기본, 외부API 폴백 |
| F-13 | MAJOR | §1.1·§1.3 | `--input-format stream-json` 상주, TTFT/부하 실측 게이트 |
| F-14 | MAJOR | §1.2 | `--max-turns`/`--append-system-prompt-file`/`--bare` 깨진 플래그 교체 |
| F-15 | MAJOR | §1.5 | 정규화 이벤트/cost 규약 + contract test |
| F-16 | MAJOR | §6.1 | RACI 소유주체 매핑, 트랙 A 분할 |
| F-17 | MAJOR | §6.2 | 모든 DoD에 람다 직접 검증 프로토콜 |
| F-18 | MAJOR | §6.3 | 라벨링/검수 영속화 + 크론 재개 워크플로우 |
| F-19 | MAJOR | §5.3 | 장애도메인 분리·예약슬롯·watchdog·폴백 |
| F-20 | MAJOR | §5.2 | 단일터널 우선 실측, 분리 시 signed token, IDOR 차단 |
| F-21 | MAJOR | §3.5 | 음성 paralinguistic 컬럼 Phase 0 선반영 |
| F-22 | MAJOR | §3.6 | C-SSRS 매핑표 + DSM-5 행동증거 매트릭스 |
| F-23 | MAJOR | §3.6 | 슈퍼바이저 논평 few-shot 참조로 격하, 1인편향 다운 |
| F-24 | MAJOR | §3.6 | arXiv ID 실재확인+수치 원문캡처, 미확인 라벨 |
| F-25 | MAJOR | §3.6 | motivated intruder test + 범주화, 합성변형 학습 |
| F-26 | MAJOR | §3.2 | 0615 페르소나/평가 분리(누수차단), 재귀학습 톤다운 |
| F-27 | MAJOR | §6.4 | Phase 2 분할(2a/2b) + 단일간트, 재귀 Phase3 이연 |
| F-28 | MAJOR | §5.4 | 공문 Phase 0 게이트, SAML 스캐폴드 선반영 |
| F-29 | MAJOR | §1.3 | 폴백 회기당 비용 실측+캐싱+batch, cost 적재 |
| F-30 | MAJOR | §5.1 | visible_to/RBAC 레이어 분리 AND게이트, RLS 기본 확정 |
| F-31 | MAJOR | §3.5 | rag_chunks 하이브리드 멀티벡터 컬럼 선반영 |
| F-32~40 | MINOR | §3.6·§5.5 | κ/ICC 임계 통일, 환각측정 정의, 캐싱 히트검증, 키관리, 위기계약, 스케일업 정의 |
---
## 8. 즉시 착수 액션 Top 5 (원본 §8 교체)
1. **엔진 PoC — 윤찬 PC에서 상주 claude -p 실증** (`--input-format stream-json` 상주 + 격리 cfg + TTFT p50/p95 실측 + 동시4회기 부하). **"검증됨" 표기는 이 실증 후에만.** [F-01·F-13·F-14]
2. **한신대 공문 질의서** — SSO 프로토콜/클레임 + **추가 축어록 N건 수급(블로킹)** + 미성년 원본 활용동의(AI학습 2차가공·DB축적·파생배포 별도항목) + NAS 국내처리. (IRB 항목 삭제) [F-04·F-05·F-28]
3. **docker-compose 스캐폴드 + Postgres 스키마(음성·RAG·cohort·audit 선반영) + Caddyfile(WS upgrade·flush -1)** — 인프라 베이스, 람다 직접. [F-21·F-30·F-31·F-07]
4. **0615 taxonomy v1.0 + 페르소나/평가 데이터 분리(누수차단)** — 시드 1례 정직표기, 골든셋 표본목표 명시. [F-04·F-23·F-26]
5. **마스킹 게이트 강제 어댑터 PoC** — Presidio 선통과 후에만 claude -p stdin 주입(우회 봉쇄) + P1 1턴 + cost 텔레메트리 + voice PoC 1턴. [F-03·F-02]
---
## 9. 잔여 — 윤찬 결정 필요 (CONDITIONAL 사유)
아래는 **람다가 단독 결정하면 월권**인 항목. 결정 후 GO 전환:
1. **s2s 2차 PoC 채택 여부** (캐스케이드 1차는 확정. 2차 옵션 유지/폐기) [F-08]
2. **fast-loop 외부 API 허용 여부** (로컬 상주 분류기 기본 vs 외부 Haiku/Solar 폴백 허용 — 데이터주권 트레이드오프) [F-12]
3. **재귀학습 fine-tuning 범위** (1차=few-shot 자동갱신만 vs 파인튜닝 포함) [F-35]
4. **자유연습 기본값** (기본 ON + 교수토글 제안 — 승인) [F-10]
5. **추가 축어록 수급 규모/일정** (n=1 해소의 전제, 한신대 협의 결과 의존) [F-04]
6. **스케일업 정의** ("클라우드 VM 이전 + compose replicas"로 합의 vs K8s 2차) [F-40]
---
*이 문서는 패치다. 원본 마스터플랜과 9개 하위 설계서의 엔진·음성전송·스키마·권한 결정은 본 문서로 통일한다. 모든 엔진 플래그는 CLI v2.1.191 직접 실행으로 검증(추측 아님).*

View file

@ -0,0 +1,296 @@
# 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
- **근거:** §0/§1.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_stage↔C-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.3/§3.2 "κ≥0.6/ICC≥0.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 BFF)·C(페르소나+분류기)·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.3/§7 "현실치 ≥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 재정렬이 선행돼야 한다.