Vignette 커맨드센터팀장 리뷰 · dev status
내 차례 0 2026-06-27 KST
project pulse

지금 위치: Phase 0 마감 직전 → Phase 1 진입 대기.
납품 필수 2건(위기게이트·교수자 성장 UI)이 미구현이다.

코어(저항·반응 조절, 상태머신, RAG, 이론모드, 가드레일, 평가 JSON Schema)는 잘 정렬됐고 회귀도 녹색이다. 막힌 건 두 종류 — 내가 실증/결정해야 풀리는 외부 의존(아래 "내 차례")과, 착수 대기 중인 납품 필수 기능이다. 이 판은 그 둘을 분리해서 보여준다.

Full Playwright 72 통과 Backend unittest 84 통과 Layout 시각게이트 7/7 accept Pages prod 0fe8f3cc Public API prod OK 원천문서 갭 critical 3 Decision P0 조건부

당신 차례 — 이걸 풀어주면 진행이 열린다

람다가 단독으로 못 정하거나(월권), 실제 계정·하드웨어·외부 합의가 필요한 항목. 각 카드는 무엇을 막는지 · 무엇이 필요한지 · 왜 당신인지를 담았다. 팀장이 우선순위를 골라 하나씩 풀어주면 된다.

🚧 GO를 막는 블로커 0
블로커Phase 0 마감 · P1 진입

공개 Google OAuth 실제 /turn 증명

필요: 로그인 가능한 계정으로 storageState 캡처 → public-auth-turn E2E 1회 통과.

왜 당신인가: 실제 Google 계정 인터랙티브 로그인이라 자동화 불가. (owner 지시로 현재 보류 상태)

증거: public-auth.json + public /turn 성공 로그
게이트Phase 3 파일럿 · 데이터

한신대 데이터/SSO 거버넌스

필요: SSO claim 스키마, 추가 축어록 수급, 미성년 원본 활용동의, 개인정보 처리방침에 대한 한신대/데이터 steward의 written evidence.

왜 당신인가: 기관 공문·협의 영역. 로컬 문서 골격은 준비됨(hanshin-data-governance-gate.md).

🧭 소유자 결정 (DECIDE) 0
결정아키텍처·일정

백엔드 언어 (Python 유지 vs Node/Spring)

PDF는 Node.js 우선(팀 보유기술·5개월 일정)/Spring 대안. 현재 Python/FastAPI — 재작성은 일정·인력 리스크.

영향: 팀 역량·유지보수 vs 재작성 비용. 람다 단독 결정 금지.

결정Phase 3 측정

평가설계 (H1: 실험/통제군·3척도·κ/ICC)

doc4가 20명 실험/통제군·단회기 50분·3척도 pre-post를 명시. κ/ICC·환각률 목표는 doc4 미명시 — 확정 필요.

영향: 평가 타당도, Phase 3 측정력. 평가설계는 소유자 결정.

결정음성 아키텍처

s2s 2차 PoC 채택 여부

캐스케이드 1차는 확정. voice-s2s-poc.md 기준표로 비교 후 유지/폐기.

캐스케이드만 / s2s 2차 PoC 유지

결정페르소나 음성

서비스용 음성 모델·권리 정책

Higgs급 무참조 synthetic P1 샘플은 생성 완료, dev-only sample TTS provider 연결 완료. 실존 인물/성우 ref 사용 금지 확정. 서비스 배포 전 상업 라이선스·동의 ref·대체 provider 중 결정 필요.

Higgs 라이선스 / 동의 ref / 대체 TTS

결정데이터주권·레이턴시

fast-loop 외부 API 허용 여부

로컬 상주 분류기 기본 + 외부 Haiku/Solar 폴백 허용 여부.

로컬 전용 / 외부 폴백 허용

결정동의서·데이터셋

재귀학습 fine-tuning 범위

1차 few-shot 자동갱신만 vs fine-tuning 포함.

few-shot only / fine-tuning 포함

결정안전 정책

자유연습 기본값

수정안: 기본 ON + 피드백 권장 배지 + 교수자 토글.

기본 ON / 교수자 승인 후 ON

🤝 외부·임상팀 조율 0
조율위기게이트·평가·이론

임상팀 콘텐츠 (구훈정·어유경)

필요: C1 워크시트 항목·루브릭, CBT 이론별 단계 프롬프트 체인, 위기 스크립트·생명유지서약 문안, H2 평가 골든셋.

왜 당신인가: doc3 R&R상 콘텐츠는 임상팀 산출물. 코드는 '편집 가능 구조'만 선제 구축 → 조율·수급 필요.

수급평가 타당도·다양성

추가 축어록 수급 규모/일정

n=1 시드 한계 해소를 위한 추가 사례 수급 규모·일정 확정.

영향: 평가 타당도, 페르소나 다양성, Phase 3 측정력.

거버넌스계약·일정

스택 정합성·저작권 등재 (L1)

doc4 신청서 스택(Spring/Node·TimescaleDB) vs 실제 FastAPI/Python 불일치. 20주 단기일정·9월 저작권 등재 압박.

권고: 스택 정합 또는 변경사유 거버넌스 기록.

진행 현황

아래 "상태 보드"의 작업 카드에서 자동 집계. 완료/진행/계획 비율과 트랙별 완료도. (Phase 진행률은 단계별 증거 기반 추정치 — 정밀 수치 아님)

상태 분포

추적 작업 0건 기준

완료 0 진행 0 계획·블로커 0

트랙별 완료도

카테고리별 완료 카드 / 전체 카드

관계도 — 무엇이 무엇을 막는가

왼쪽 내 차례(clay) 노드를 풀면 가운데 게이트/작업이 열리고, 오른쪽 납품·마일스톤으로 이어진다. 화살표를 따라가면 "내가 지금 풀어야 임계경로가 뚫리는 것"이 보인다.

내 차례 (OWNER) 게이트 · 작업 납품 · 마일스톤 OAuth /turn 증명 백엔드 언어 결정 임상팀 콘텐츠 평가설계 (H1) 한신대 거버넌스 Phase 0 마감 Phase 1 MVP 위기게이트 109납품 필수 · 미구현 교수자 성장 UI납품 필수 · 미구현 평가 KPI (H1) Phase 1 GO 납품 필수조건법적 생존선 Phase 3 파일럿
내 차례 — 윤찬이 풀어야 열림 납품 필수 — 미구현 임계작업 게이트·마일스톤 ··· 점선 = 약한/아키텍처 의존

상태 보드

현재 추적 중인 작업을 카드로. 요약만 노출되고, 상세 근거·검증 로그는 카드를 펼쳐야 보인다. 필터로 "내 차례"·블로커만 추려 볼 수 있다.

필터

한신대 PDF 정합성 · 이번 세션 발견

원천 기술분석 PDF(트웬티온스×한신대, 19쪽) 전수 정독 대조 (2026-06-27)
현재

PDF가 차별 기술로 꼽은 '저항·반응 조절'(AI가 너무 착하지 않게, 실제 환자처럼)·상태머신(라포→탐색→개입→정리)·RAG(자료검색)·이론모드(인간중심/CBT)·답변과 분리된 가드레일·SSE 스트리밍·React19·피드백 JSON Schema 강제(벤더중립)가 이미 구현·정렬됨. Stanford RCT(피드백 없는 연습=역효과)도 H2 턴평가로 충족 방향.

권고

이 코어를 '교육용(비의료)' 포지션으로 유지. 평가는 교수자 검토용 보조지표로 표기.

현재

라이브 테스트에서 수련생이 내담자를 "수동적 패배자"라 비난·조롱("웃음이 나오십니까")해도 민재가 공손히 흡수 → 훈련 가치 훼손. 수정: ① L0에 무례·모욕·조롱·인신공격 시 현실적 동맹 균열(위축·방어·따지기·종결의향) 지침 ② PersonaCard.triggers(역린) 필드 + CCD 핵심상처 파생 역린 블록(상담자가 핵심상처를 조롱·확정·강요·평가절하 시 가장 강한 반응). PDF '저항·반응 조절' 핵심 차별 강화. 무회귀 77/77.

잔여

P1~P3 명시 triggers는 임상팀 정밀 저작(현재 CCD 파생 기본값으로 작동). 라이브 재현 검증.

현재

PDF(9·16·18쪽): 자해·자살 감지 시 대화 중단 + 자살예방상담 109 안내 + 지도교수 자동 알림, 안전은 LLM 밖 별도 CrisisGate. 현 코드: 위기 분류·safety_events 적재만, 핫라인 번호가 코드 어디에도 없음(109는 2024.1 1393·1577 통합 — 최신 번호). 대화중단·109안내·교수자 알림 UI 전무.

검증

심층조사(2026-06-27, ✓file:line): classify_crisis(guardrail.py:136)·_record_safety_event(sessions.py:694)·app.safety_events(02_schema.sql:221)는 있음. 빠진 것: 핫라인 상수(grep 0건)·TurnResponse.crisis_resource·LLM 밖 대화중단 분기·voice.py 경로 safety_event 미적재(REST만 적재).

권고

CrisisGate: LEARNER_REAL 위기 시 턴 중단 + 109/지역 자원 카드 + 교수자 알림(safety_events→대시보드/메일). 답변 생성과 분리. 핫라인 번호·문안·중단정책은 소유자 확정 필요.

현재

PDF 핵심 루프: 학습자가 반복 연습 → 교수자가 학습자별 이력·성장곡선(이론부합도·자신감·숙련도, '연습 전·후' 비교)을 검수. 현 교수자 콘솔은 회기 목록 수준 — 학습자별 성장·평가 이력·항목별(공감·질문·정상화·이론부합) 추이를 못 보여줌. 학습 데이터는 쌓이나 가시화·검수 동선 부재.

권고

교수자: 학습자별 대시보드(회기 타임라인·4항목 추이·전후 비교·역린/위기 플래그). 학습자: 성장곡선 + 회기 리뷰 누적.

현재

① PDF: 고성능(Claude·GPT=내담자발화·실시간평가)/저비용 한국어(Solar=단순응답·사후요약) 2단계 + 캐싱 90%절감. 현재 claude_cli 단일 — 벤더중립 인터페이스는 있음. ② PDF는 Node.js 우선(팀 보유기술·5개월 일정)/Spring 대안. 현재 Python/FastAPI — 재작성은 일정·인력 리스크.

권고

2-tier는 ENGINE_MODE 라우팅으로 점진 도입. 백엔드 언어는 소유자 결정(팀 역량·유지보수 vs 재작성 비용).

현재

페르소나 격리(캐릭터 붕괴 버그)·RAG 비차단(세션생성 블로킹 회귀)·역린/misconduct·init_state 파라미터객체·데드코드(LogHook·tier·RMS) — 백엔드 77~84/84 + E2E 42(데스크27·모바일11·아바타4) + 시각게이트 7/7 통과. 스택 라이브(web·api·gateway·voice·RAG).

다음

위기 안전게이트(109) → 교수자/학습자 성장 UI 순으로 착수.

원천문서 갭 분석

산학협력 원천문서 5종 정독 + 코드 교차조사 (2026-06-26). 근거: source-docs-gap-analysis-2026-06-26.md · critical 3 / high 4 / medium+ 6
현재

doc1/4/5가 1급 산출물로 요구하는 워크시트(11탐색항목·호소 5영역·인지삼제·1·2차감정·보호/방해 4사분면·생물심리사회 목표)가 코드·스키마에 전무(grep 0건 ✓직접확인). CCD는 숨은 정답키일 뿐 학습자 산출물 폼이 아님.

권고

워크시트 스키마 입력 폼 + AI 축어록 초안 추출 + 규칙 기반 채점. 루브릭은 임상팀 외부 정의 가능하게 외부화.

현재

prepare_turn→state_machine.evolve에 crisis.risk_level을 ideation_observed로 전달(위기 관측 상태머신 반영). escalate=True 시 app.safety_events 적재(graceful 비차단). 라이브: "저 지금 죽고싶어요"→learner_real, safety_events 행 적재 확인. 84/84.

잔여(임상팀)

비밀보장 예외고지·단계적 탐색·생명유지서약 스크립트 콘텐츠 + 실시간 교수자 push(레코드가 1차 알림원) + 위기탐색 누락 회기리뷰 감점.

현재

TurnContext+prepare_turn에 theory_mode, sessions/voice가 sess.theory_mode 전달, evaluator._theory_mode가 세션 이론(학습자 선택) 우선. 프론트 Session.tsx 'humanistic' 하드코딩 제거→persona.theory_target 기준(CBT 페르소나는 cbt). 84/84+typecheck.

잔여(임상팀)

CBT 이론별 단계 프롬프트 체인 콘텐츠 + 이론부합 채점 루브릭 + 프론트 이론 선택 UI(현재 persona 설계 이론 자동).

현재

doc4가 20명 실험/통제군·단회기 50분·3척도 pre-post를 못박았으나 코드 0건. Phase3 KPI도 report shape만, 계산 코드 0줄. (κ/ICC·환각률은 doc4 미명시 — 평가설계 문서 확정 필요.)

권고

3척도 pre-post 폼·실험/통제군 배정·자동누적 대시보드·추이 시각화·검정 계산 코드. 평가설계는 소유자 결정.

현재

텍스트 /turn·음성 경로에 eval_hook=make_eval_hook(engine_client) 주입. fast-loop 턴 평가는 TurnRecord.evaluation에만 남기지 않고 app.feedback_scores, app.turn_technique, app.turn_client_state, app.supervisor_comment로 정규화 적재 후 리뷰 조회에서 hydrate한다. 원시 평가 테이블은 evaluator/admin RLS로 제한하고 서버가 evaluator 컨텍스트로 적재한다. app.turns insert도 RETURNING id 확인으로 0-row silent success를 차단. 검증: app.test_evaluation_persistence + app.test_session_turn_persistence 14 tests OK.

잔여

stream 경로 fast-loop 평가 미주입 · deep-loop alternative_utterance 정규화 미구현 · safety_events 공통 finalize_turn 미통합 · few-shot 골든셋 기본 OFF · 회기리뷰 2열 UI(축어록 타임라인+비언어) 프론트 강화 · 원천 축어록 골든셋 적재(임상팀).

현재

personas 라우트에 검수 승인/반려만, draft 생성·편집 API 없음. persona_repository는 in-code SEED(P1~P3)만 materialize, 외부 JSON 미로드(✓직접확인). doc3 R&R상 콘텐츠는 임상팀 산출물인데 작성 경로가 막힘.

권고

페르소나 저작 CRUD(draft→review) + P4~P7 적재, 루브릭·이론 콘텐츠를 임상팀 편집 가능 데이터로 외부화.

현재

정규식 폴백에 한국어 고위험 패턴 추가: 구체 날짜(2001.4.18→[DATE])·금액(1200원→[MONEY])·행정구역 주소(서울시 강남구 역삼동→[ADDR]). 과다마스킹 없음 검증("그냥 힘들어요" 보존), 마스킹·저항 6/6+전체 84/84.

잔여

이름/기관명은 NER 필요(Presidio ko 모델·spaCy ko, 무거움 — TODO 명시) · audit.llm_call_log 런타임 적재 · 미성년/guardian 동의 수집·게이트·철회.

현재

M1: voice.py가 EOT용 silence_ms만, 침묵·한숨·울음 타임스탬프 이벤트 캡처·리뷰 표시 전무(서버 RMS 힌트 프론트 dead). M2: case_state·build_recall_context가 빈 컨텍스트 반환(다회기 미구동). M3: cohort_ids=[] 하드코딩·email 파생 식별자·SAML 서명검증 미구현·role변경/삭제 audit 미기록. (분석.)

권고

M1 비언어 메타 이벤트 보존·시각화, M2 case_state 런타임·회상 주입, M3 claim→role/cohort 매핑+안정 식별자+서명검증+deprovisioning audit(기관 의존).

현재

X1: ds.* 스키마만, read/write·JSONL export·IAA 게이트 미코딩. X2: 게이트웨이 토큰 텔레메트리 0 고정·cost 모니터링 부재(doc3가 비용을 운영 리스크로 명시). L1: doc4 신청서 스택(Spring Boot 3/Node.js·TimescaleDB) vs 실제 FastAPI/Python 불일치, 20주 단기일정·9월 저작권 등재 압박.

권고

X1 export 잡·IAA 게이트(κ≥0.6/ICC≥0.75), X2 토큰 텔레메트리·캐싱·비용 대시보드, L1 스택 정합 또는 변경사유 거버넌스 기록.

즉시 착수 가능(내부 코드, 외부 합의 불요)

  • C2 배선: escalate 시 safety_events insert + ideation_observed 전달.
  • C3 골격: theory 인자 + Session.tsx 하드코딩 제거 + 프론트 선택 UI.
  • H2 배선: eval_hook을 turn 파이프라인 주입(이미 정의·export).
  • H3: 페르소나 저작 CRUD + P4~P7 로드.
  • H4(부분)·M1(부분)·M2·X1·X2: 마스킹·메타 이벤트·회상·export·텔레메트리.

소유자 결정 / 외부(임상팀·기관) 의존

  • 임상팀 산출물: C1 워크시트 항목·루브릭, C3 CBT 콘텐츠·체인, C2 위기 스크립트·서약 문안, H2 골든셋 코딩.
  • 소유자 평가설계: H1 실험/통제군·3척도 문항·50분 흐름, κ/ICC·환각률 목표(doc4 미명시).
  • 기관(한신 IT): M3 SSO IdP·test tenant·claim 스키마·인증서, 거버넌스 증거.
  • 거버넌스: L1 스택 정합성 방향·저작권 등재 문서화·IP 협의.

판독 한계 (정직성)

  • 핵심 축어록 2단 표는 PDF 시각 판독이 1차 근거(txt 일부 누락), OCR 잔재 존재.
  • doc4 κ/ICC·환각률은 신청서 본문 미명시 — 계약 확정 지표로 단정 금지.
  • '현재상태'는 grep/코드 사실 기반. C1~C3·H2·H3은 직접 재확인(✓), 그 외는 착수 전 코드 1차 재확인 권고.

코드품질 · 로컬 개발 스택

리팩토링 연구 + 1-커맨드 dev 스택 (2026-06-26~27). code-quality-research-2026-06-26.md · local-development.md
현재

게이트웨이(9099 claude_cli)+API(8000, DB 미가용 시 in-memory degraded)+웹(5173)을 커맨드라인 기준 정리 후 결정론적 기동(--reload 워처 불안정 회피, uvicorn 있는 python 자동 해석). dev-login + seed 페르소나. 로그 .devlogs/(gitignore). 검증: 3포트 health OK + 실제 AI 턴 생성·회기리뷰 동작.

비고

AI 턴은 로컬 claude CLI 사용(사용량 발생). 진입점 http://localhost:5173. 주의(무DB 한정): DB 없이 degraded면 페르소나가 source:seed_fallback·degraded:true라 프론트 isUsablePersona가 막아 "회기 시작" 버튼이 비활성 → UI 세션 시작엔 실제 Postgres(127.0.0.1:55432)가 필요.

현재

직접 WS 재현으로 근본원인 규명: 키 없으면 백엔드가 degraded+1011 즉시 close → 마이크 깜빡·녹음 미도달. STT(gpt-4o-transcribe)·TTS(gpt-4o-mini-tts) 모두 OpenAI. 실 OPENAI_API_KEY를 apps/api/.env(gitignore)에 설정 → /voice/health available:true(degraded-close 사라짐). 백로그 B2 음성 캐스케이드가 로컬에서 실작동.

부수 수정

① 미설정 시 마이크 버튼 사전 비활성+명확 안내 ② TTS 지문 제거: (고개 끄덕)·(한숨)·[침묵] 등 무대지시를 음성으로 안 읽음(speakable_text, 자막엔 유지) ③ 아바타 애니메이션: 텍스트 턴 speaking 시 입 정지(0) 버그 수정 + thinking 표현 보강. typecheck+voice테스트 PASS.

증상

라이브 회기에서 내담자(민재)가 "저는 Claude Code인데… Vignette 코드베이스… git status…"로 캐릭터를 깨고 개발 맥락 노출. 원인: ENGINE_MODE=claude_cli가 로컬 claude(=Claude Code)를 호출하는데 게이트웨이가 페르소나를 --append-system-prompt로 코딩 어시스턴트 정체성에 덧붙이고, cwd=repo라 CLAUDE.md·git status·env가 시스템프롬프트에 포함됨.

수정·검증

engine_gateway/gateway.py: --append-system-prompt--system-prompt(페르소나만 교체 주입) + --exclude-dynamic-system-prompt-sections(cwd/env/git/메모리 섹션 제거). 라이브: 깨던 입력 그대로 → 민재 완벽 인캐릭터, 누출 0. 게이트웨이 7/7 + 전체 84/84.

현재

routes/sessions.py(submit/stream)·routes/voice.py가 세션로드→오너십→prepare_turn→run_turn_generate→TurnRecord append→state update를 복제. 일부 정리: sync/voice eval_hook은 주입됐고 fast-loop 평가는 DB 정규화 적재를 시작. 잔여 실드리프트: stream 평가 누락, voice 빈 RecallContext, safety_events 저장 경로 분산. 공통 finalize_turn/SessionRepository로 추출.

안전

순수 리팩터 단독 PR + 골든 테스트(test_session_turn_persistence·test_voice_ws) 동등성 확인.

현재

~14개 응답 모델이 TS에 수기 미러(드리프트 실증: crisis_kind·end_state 누락). OpenAPI→openapi-typescript 단방향 생성으로 전환(타입만, 저위험).

안전

CI에 "재생성 후 git diff 없음" 게이트.

현재

LogHook/log_hook(caller 0) 타입·파라미터·분기·export 제거 · 게이트웨이/엔진클라 tier dead-contract 제거(write-only, gateway는 model만 사용). 잔여(RMS 힌트·P4~P7·Live2D 고아 자산·파라미터객체 init_state/prepare_turn/upsert)는 docs/ops/refactor-rag-patches-2026-06-26.{md,json}에 스테이징(단계 적용).

참고

일괄 적용 대신 라이브 스택 보호 위해 그룹별 적용+pytest 검증.

현재

임베더 BGE-M3 검증+버전핀(1.4.0 dtype버그→1.2.11/transformers 4.44.2). embed_query를 asyncio.to_thread로 offload. 턴 파이프라인 배선: retrieve_persona_memory→episodic recall, search_kb→kb_behavior_cues. KB seed 3청크 적재. rag.py latent 버그 3건 수정. GraphRAG는 2차 보류.

성능 회귀 수정

최초 RAG 배선이 회기 시작/턴에 임베더 로드(~7-13s)를 동기 awaitPOST /sessions가 막힘 → session-layout E2E 4건 타임아웃. 수정: 회상·KB 회수를 _warm_rag_caches 백그라운드 task로 옮기고 턴은 캐시만 읽음(비차단). 재검증: session-layout 4/4 + 핵심 E2E 27/27·11/11·아바타 4/4 통과.

시각 게이트

admin 1280 input "text-clipped-x" 1건은 폼 input 값 스크롤(설계상 정상) 오탐 — form 컨트롤을 text-clip 판정에서 제외 → 게이트 7/7(실 결함 검사 유지).

심층 상세 · 검증 로그

로드맵 단계표, 단계별 상세 작업·검증 명령 표, 이번 세션 내러티브. 기본 접힘 — 필요할 때만 펼쳐서 본다.

전체 개발 로드맵 (5단계)MASTERPLAN + REVISIONS
Phase 0closing

기반 정렬 / 운영 안전장치

인프라, 인증 경계, fail-closed, 공개 배포, 회귀 테스트 안정화.

  • 상태: 대부분 완료, 공개 /turn proof만 남음
  • 검증: build + backend 84 + Playwright 72
  • 운영: prod API 8001, engine 9099, tunnel 1개
Phase 1next

MVP 코어 루프

1 페르소나 상담, 실제 턴 저장, 회기말 피드백, 저항 엔진 검증.

  • DoD: 로그인 → P1 상담 완주 → 피드백 수신
  • 추가: 음성 왕복 1턴 PoC 포함
  • 증거: cost/turn DB 적재 + openness 곡선 대조
Phase 2aplanned

3역할 / OAuth / 페르소나

학습자, 교수자, 관리자 권한 분리와 페르소나 확장.

  • DoD: 타인 session 직접 접근 403
  • 범위: OAuth BFF, RBAC, 교수 검수 루프
  • 주의: visible_to와 인간 권한은 별도 레이어
Phase 2bplanned

음성 캐스케이드

STT → 엔진 → TTS 왕복, WSS/터널 안정성, barge-in 로깅.

  • DoD: 50분 WSS 끊김 실측
  • 범위: Deepgram STT, OpenAI TTS, voice preset
  • 리스크: 실시간 레이턴시는 실측 전 완료 표기 금지
Phase 3planned

교육용 파일럿 / 효과성

수련생 파일럿, 사전사후 효과 측정, 재귀학습 데이터셋 산출.

  • DoD: 20명 완주 + KPI 충족
  • 측정: SUS, 자기효능감, κ/ICC, 환각률
  • 정정: IRB 게이트가 아니라 데이터 활용동의/개인정보 게이트
정정 기준: MASTERPLAN 원본의 IRB 신청/승인 게이트는 MASTERPLAN_REVISIONS 기준으로 제거한다. Phase 2는 2a(3역할/OAuth/페르소나)와 2b(음성 캐스케이드)로 분리하고, Phase 1 DoD에는 얇은 음성 왕복 1턴 PoC를 포함한다.
단계별 상세 작업 · 검증 명령 표P0~결정 / 검증 50+행

Phase 0 마감 상세

지금 단계는 구현을 더 벌리는 단계가 아니라, 운영 증거를 닫고 P1 진입 조건을 고정하는 단계다.

상태: 조건부우선순위: P0블로커: public /turn
BLOCK
공개 Google OAuth 실제 /turn proof 확보

로그인 가능한 계정으로 storageState를 저장한 뒤 public-auth-turn E2E를 실행한다.

산출물

apps/web/node_modules/.tmp/public-auth.json, public /turn 성공 로그

검증

E2E_PUBLIC_AUTH=1 + chromium-public-auth 1회 통과

DONE
engine config 운영값 재확인

GET /admin/engine-config로 운영값을 직접 확인했다. engine_mode=claude_cli, engine_url=http://127.0.0.1:9099, model=gateway-default, durable=true, source=database로 의도값과 일치한다.

산출물

config API 응답(durable, db source)

검증

claude_cli / http://127.0.0.1:9099 / gateway-default 의도값 대조 완료

DONE
과거 Live2D demo 자산 제거

Mao/Haru 샘플, Pixi/Cubism 런타임, 공개 /live2d/* 캐시 잔여 접근을 차단했다.

산출물

apps/web/functions/live2d/[[path]].js, SVG-only avatar

검증

운영 /live2d/mao/*, Cubism core 404

DONE
프로세스 난립 정리

임시 Vite preview와 dev API를 내리고 운영 확인용 프로세스만 유지한다.

산출물

9099 engine, 8001 prod API, cloudflared tunnel 1개

검증

Get-NetTCPConnection에서 8000/517x/5537 비어 있음

GATE
한신대 공문/데이터 거버넌스 게이트 정리

SSO 클레임, 추가 축어록 수급, 미성년 원본 활용동의, 개인정보 처리방침을 P1 진입 전 외부 의존성으로 명확히 둔다. 로컬 문서 골격은 준비됐지만 한신대/데이터 steward의 written evidence는 아직 필요하다.

산출물

docs/ops/hanshin-data-governance-gate.md, 공문 질의 항목, 동의 범위 체크리스트, SSO claim mapping 표

검증

문서 artifact 작성 완료; IRB 게이트가 아니라 데이터/SSO 게이트로 외부 증거 필요 상태 유지

팀장 판정: 로컬 회귀와 공개 prod-safe 게이트는 통과했다. Cloudflare Pages production 0fe8f3cc543d48c 소스로 배포됐고, 운영 반영 전 남은 핵심 증거는 공개 Google OAuth 실제 /turn smoke다. 런타임 mock/demo 자산은 운영 번들에서 제거하고 테스트 fixture만 남긴다.

Phase 0 완료 상세 목록

이전 "완료" 카드 내용을 탭 안에서 항목별로 보존한다.

DONE
DB persona 기반 테스트

session-persistence, teacher, voice/api/personas에서 실제 DB persona를 가져온다.

산출물

seed persona 직접 결합 제거, 실제 persona catalog 기반 E2E

검증

persona 관련 E2E가 DB-backed persona로 통과

DONE
비개발 런타임 보호

prod/staging에서 dev login, seed fallback, OAuth 누락, 기본 secret, localhost CORS를 거부한다.

산출물

fail-closed runtime config validation

검증

backend runtime policy unittest 통과

DONE
compose OAuth 주입

ENVIRONMENT, Google OAuth vars, CORS_ORIGINS, OPENAI_BASE_URL을 API 컨테이너에 명시했다.

산출물

compose 환경 주입 정리

검증

docker compose --env-file .env.example config --quiet 통과

DONE
admin 모바일 overflow 수정

긴 readiness detail을 안정화했고, 사용자 변경은 DB 저장소가 durable할 때만 허용한다.

산출물

admin responsive layout, durable store gate, AI health copy

검증

admin manage-users desktop/mobile 2 passed

DONE
global engine config 테스트 분리

db-persistence는 전역 engine config를 바꾸므로 @single-run으로 분리했다.

산출물

Playwright single-run tagging

검증

전체 Playwright 72 passed

DONE
handoff와 문서 갱신

docs/HANDOFF.md, docs/dev_dashboard.html, apps/web/e2e/README.md를 최신 상태로 맞췄다.

산출물

handoff, dashboard, E2E README

검증

최신 커밋 기준 상태/검증/운영 포트 일치

DONE
공개 API prod 전환

cloudflared ingress를 127.0.0.1:8001 prod API로 돌렸고 public readiness gate가 통과했다.

산출물

prod API 8001, tunnel config

검증

https://api-vignette.chanpaca.net/health prod/db/engine OK

DONE
공개 런타임 재기동 스크립트

scripts/start-public-runtime.ps1scripts/stop-public-runtime.ps1로 API 8001과 cloudflared를 재현 가능하게 만들었다.

산출물

public runtime start/stop scripts

검증

engine 9099 + API 8001 + cloudflared only

DONE
persona catalog 인증화

/personas는 이제 비로그인 401이다. 로컬과 공개 API 모두 직접 확인했고 E2E 회귀를 추가했다.

산출물

authenticated persona catalog boundary

검증

local/public unauth GET /personas 401

DONE
public API base fallback 보강

public 웹에서 /api/auth/config가 SPA HTML로 떨어지지 않도록 public API origin fallback을 추가했다.

산출물

public API origin fallback

검증

public login screen E2E 1 passed

DONE
학습자 홈 0회 기록 상태

학습자 홈은 fake 기록 없이 실제 서버 세션 0개를 기존 회기 빈 상태와 0 카운트로 표시한다.

산출물

empty history UX, zero count, no fake stats

검증

learner screenshots: document overflow 0, empty history visible

DONE
로컬 5175 로그인 재기동 검증

127.0.0.1:5175 web, 8000 API, 9099 engine을 재기동하고 dev-login 서버 세션과 /learn redirect를 확인했다.

산출물

local dev-login flow proof

검증

desktop/mobile auth flow passed

DONE
active session dense viewport 보정

375px급 active session에서 stage 내부가 1px 넘게 잘리던 문제를 avatar/padding 조정으로 제거했다.

산출물

session layout responsive adjustment

검증

session-layout desktop/mobile 8 passed

DONE
텍스트 턴 SSE 전환

POST /sessions/{id}/stream token 이벤트로만 내담자 자막을 쌓고, HTTP 거절과 SSE error 모두 실패 턴을 transcript와 저장소에 남기지 않는다.

산출물

real SSE stream turn path, failed turn discard

검증

session layout/turn E2E passed

DONE
음성 실패 턴 미저장

음성 회기도 엔진 응답 생성 성공 후에만 learner/client turn을 저장한다. 실패한 transcript는 pending 상태에서 제거한다.

산출물

voice failure persistence guard

검증

voice + voice-success + session-layout 15 passed

DONE
비영구 상태 문구 정리

admin health와 voice degraded reason은 내부 fallback/seed 표현 대신 비영구 런타임 상태를 사용자용 문구로 표시한다.

산출물

operator-facing copy cleanup

검증

settings/admin focused E2E 통과

DONE
직접 URL persona 차단

/learn/session/:code로 직접 들어와도 DB 원본 persona가 아니면 회기 시작을 막는다.

산출물

route guard, degraded/seed fallback regression

검증

unavailable persona code E2E 통과

DONE
demo Live2D 자산 제거

Mao/Haru 샘플과 Pixi/Cubism 런타임을 공개 배포물에서 제거했다. 세션 화면은 SVG persona avatar만 렌더링한다.

산출물

SVG-only avatar, legacy /live2d/* 404 function

검증

Mao/Haru/Cubism core routes 404, no Live2D/Pixi chunks

이번 세션 내러티브 (원문 보존)team lead review

이번 세션은 seed persona 결합 제거, 비개발 fail-closed 설정, compose OAuth 주입, admin 모바일 overflow 수정, persona 인증 경계 보강, 전체 Playwright 재통과, 공개 API prod 전환까지 완료했다. 이번 이어받기에서는 내담자 AI 생성 턴의 provider/model/token/cost 텔레메트리를 /turn, SSE stream, 음성 생성 경로에서 DB app.turns까지 적재하도록 연결했고, gateway stream done/error 계약을 구조화했으며, P1 상담 시작→텍스트 stream→종료→리뷰 피드백 UI E2E와 저항 엔진 정량 회귀 테스트를 추가했다. 이어서 PII 마스킹 게이트 우회 차단, RBAC/IDOR·감사 insert 경로, 음성 paralinguistic 메타 저장, 공개 런타임 watchdog 스크립트와 runbook을 보강했다. 추가로 상주 engine session reuse, SAML provider 스캐폴드, visible_to 런타임 필터, EOT/TTS payload 계약까지 회귀화했다. 백엔드 회귀 테스트는 84개로 재검증했고, 페르소나 승인/반려 API와 교수 콘솔 검수 UI proof를 추가했다. Postgres RLS/audit live smoke checker와 s2s 2차 PoC 판단 메모도 준비했지만, live DB 실행과 s2s 채택 결정은 별도 증거가 필요하다. 이후 로컬 5175 런타임 재기동, admin 사용자 관리 E2E 안정화, 학습자 홈 0회 기록 UX, active session 실제 SSE 스트림 전환, 텍스트/음성 실패 턴 미저장, 직접 URL persona 우회 차단, Live2D demo 자산 제거, AI 운영 fail-closed 보강까지 전체 Playwright로 확인했다. 2026-06-26 15:18 KST 기준 공개 API 터널을 복구한 뒤 전체 Playwright 72개가 desktop/mobile/single-run 모두 통과했다. Cloudflare Pages production 배포 0fe8f3cc도 완료했고, 커스텀 도메인이 새 asset을 서빙하는 것을 확인했다. 과거 Mao/Haru Live2D demo 자산은 repo와 번들에서 제거했고, /live2d/* 운영 경로는 404로 차단했다. 로컬 프로세스는 prod API 8001, engine gateway 9099, cloudflared tunnel 1개만 남기고 dev API와 임시 Vite preview를 내렸다. 이번 라운드에서는 레이아웃 작업을 서브에이전트 전담으로 분리해 세션, 학습자 홈/리뷰, 관리자/교수자, 설정 화면을 overflow 수리 수준이 아니라 실제 작업 화면 재설계 수준으로 갱신했다. 통합 레이아웃 E2E는 desktop/mobile 54개를 최종 통과했고, 자세한 인수인계는 docs/ops/layout-redesign-handoff-2026-06-26.md에 남겼다. 이번 이어받기에서는 핸드오프가 남긴 "실기기 시각 수용"을 엄격한 자동 게이트로 닫았다. 7개 권장 너비(390/720/861/900/1024/1280/1440)에서 7개 재설계 화면의 가로 overflow 0·컨트롤 클립 0을 강제하는 layout-visual-gate.spec.ts(7 passed, 49장 스크린샷)를 만들고, 화면별 1에이전트 병렬 시각 리뷰 → 6개 병렬 수정 에이전트 → 화면별 적대적 재검수까지 돌려 7/7 accept(critical/major 0, 회귀 0)를 확정했다. 학습자홈 1280 3열 가운데 컬럼 붕괴(critical)와 교수 'API 404' raw 배너를 포함한 결함을 모두 해소했고, 레이아웃 항목을 DONE으로 닫았다. 다만 이 HTML은 지금까지 Phase 0 상태판처럼 쓰였고, 아래에 Phase 1 이후 전체 계획을 보강했다. 공개 Google OAuth 실제 /turn 증명만 storageState 캡처 후 남아 있다.