vignette/docs/guides/source-docs-and-gaps.md
2026-06-29 08:12:14 +09:00

37 KiB

원천문서·갭 로드맵 가이드

한신대 산학협력(구훈정 교수) 원천문서 5종과 거기서 도출된 **갭(부족분)**의 인덱스/로드맵을 한 장으로 정리한 가이드다. 갭 항목의 상세 근거는 docs/ops/source-docs-gap-analysis-2026-06-26.md에, 상태·결론의 권위 기준(SSOT)은 docs/dev_dashboard.html"원천문서 갭 분석" 섹션에 있다. 이 가이드는 그 두 산출물을 요약·링크한다.


0. 이 문서를 읽는 법 (3분)

  • 무엇인가: Vignette(AI 심리상담 시뮬레이션 훈련 플랫폼)가 산학협력 원천문서가 요구하는 임상 사양 대비 어디가 비어 있는지를 심각도(critical/high/medium+)로 분류한 인덱스다.
  • 왜 있는가: 어떤 갭이 "코드만 고치면 되는 것"이고, 어떤 갭이 "임상팀/기관/소유자 결정이 선행돼야 하는 것"인지 구분해 착수 순서를 정하기 위함이다.
  • 권위 순서(SSOT):
    1. docs/dev_dashboard.html → "원천문서 갭 분석 (2026-06-26)" 섹션 = 상태·결론의 단일 진실원천(SSOT).
    2. docs/ops/source-docs-gap-analysis-2026-06-26.md = 그 SSOT 항목의 상세 근거(원천문서 요지·항목별 근거·검증 메모).
    3. 이 가이드 = 위 둘의 요약 + 빠른 진입 인덱스.
  • 핵심 R&R 한 줄: 콘텐츠(워크시트 문항·채점 루브릭·이론 프롬프트·위기 스크립트·골든셋)는 임상팀(구훈정·어유경) 소유, 기술팀은 "편집 가능한 구조"만 선제 구축한다. (출처: doc3 회의록 R&R)

원천 산출물 바로가기

산출물 경로 역할
갭 상세 분석 docs/ops/source-docs-gap-analysis-2026-06-26.md 원천문서 요지·항목별 근거·직접검증 메모·판독 한계
SSOT 대시보드 docs/dev_dashboard.html (# "원천문서 갭 분석" 섹션) 상태·우선순위의 권위 기준, 갭 요약 카드
데이터 거버넌스 게이트 docs/ops/hanshin-data-governance-gate.md H4/M3 관련 거버넌스
백로그 docs/ops/backlog-2026-06-26.md 실행 작업 목록
레이아웃 핸드오프 docs/ops/layout-redesign-handoff-2026-06-26.md UI 재설계 맥락

1. 원천문서 5종 (한신대 산학협력 · 구훈정 교수)

5종 문서를 PDF로 변환해 시각 정독(에이전트 1/문서)하고 Vignette 코드베이스 4개 도메인을 교차 조사한 뒤, 1차 종합 → 적대적 비평 → 최종 재구성한 결과다(워크플로우 source-docs-gap-analysis, 에이전트 12, 토큰 약 1.11M).

ID 문서 핵심 함의(Vignette 그라운드 트루스)
doc1 청소년·대학생 사례 워크북(3·4장) 첫 회기 축어록→사례개념화→목표·전략 표준 분석틀 + 두 사례(비자발 청소년/자발 대학생). 페르소나 완성형 스펙, openness 곡선 정량 근거, 위기 프로토콜, 다회기 아크(2~10회기), 회기리뷰 주석 포맷의 기준점.
doc2 인간중심접근 사례·프로토콜(4장) 미혼모 3회기 상담의 인간중심 사례개념화 정답지. theory_mode=humanistic 1급 필드, 공감·반영 정확도 기반 openness, 회기리뷰 채점 루브릭의 직접 근거.
doc3 산학협력 회의록(2026-06-08) 3주체(임상팀 구훈정·어유경 / 트웬티온스 / 사업단 김시윤) 협력·거버넌스 확정. R&R: 콘텐츠·평가기준=임상팀 소유, 구현=기술팀. 평가 루브릭은 임상팀이 외부 정의·수정 가능해야 함. AI API 비용을 운영 리스크로 명시.
doc4 산학협력 신청서(공식 계약) 기간(2026.5.18~9.30, 20주)·예산·평가지표·산출물·서약의 권위 원천. humanistic+CBT 2종 필수 이론을 '단계적 프롬프트 체인'으로 계약, 3척도 사전사후·20명 실험/통제군·단회기 50분, 9월 저작권 등재, IRB 100% 준수. 기술스택 명시(Spring Boot 3/Node.js·TimescaleDB — 실제 FastAPI/Python과 불일치).
doc5 사례개념화 워크북(3장, 상호작용 분석 추가본) 비자발 청소년(자살사고) 축어록(상1~63)에 기법 코딩. 회기리뷰 루브릭·기법 코딩 택소노미(κ/ICC 스킴)·페르소나 사양·종결 규칙의 직접 근거.

주의(doc4 KPI 범위): κ/ICC·환각률은 신청서 본문에 미명시('정량 신뢰도 확보' 수준). 계약 확정 지표로 단정하지 말 것 — 별도 평가설계 문서로 확정 필요.


2. 갭 로드맵 — 심각도 우선순위

심각도 분류: critical 3 / high 4 / medium+ 6. C1의 "구조 전무"와 저장형 제출물 부재는 2차로 해소됐고, 3차에서는 임상팀 루브릭을 외부 JSON으로 받을 schema/loader/validation scaffold까지 추가했다. 4차에서는 교수자 수동 검수 상태 저장/표시 골격까지 연결했다. 임상 루브릭 콘텐츠·AI 채점·검수 정책 고도화는 계속 추적한다. 는 작성자가 코드 grep으로 직접 재확인한 항목, (분석)은 분석 결과로 착수 전 코드 1차 재확인 권고.

Critical (3)

ID 현재상태 권고 근거
C1 사례개념화·치료계획 산출물 저장형 구조 4차 구현·루브릭 외부화 scaffold·수동 교수자 검수 골격 완료·채점/정책 잔여 SessionReviewResponse.caseWorksheet가 축어록 근거 기반 초안을 제공하고, 리뷰 화면에서 학습자가 편집한 워크시트를 PUT /sessions/{id}/review/worksheetapp.case_worksheet에 저장한다. 이후 GET /reviewsaved_by_learner 저장본을 자동 초안보다 우선 반환한다. 3차에서는 data/rubrics/case-worksheet-rubric.json, Draft 2020-12 schema, app.services.case_worksheet_rubric, scripts/check-case-worksheet-rubric.py를 추가해 임상팀 확정 루브릭을 코드 수정 없이 받을 scaffold를 만들었다. 현재 rubric은 scaffold_only/scoring_enabled=false이며 서버 생성 워크시트 5개 section/28개 item key와 일치하는지만 검증한다. 템플릿 key source는 CASE_WORKSHEET_SECTION_SPECScase_worksheet_template_item_keys()로 명시해 validator/CLI/test가 더미 턴 없이 같은 생성 spec을 참조한다. 4차에서는 기존 app.session_review_statusworksheet_status/worksheet_note/worksheet_reviewed_at을 붙이고, PUT /teacher/sessions/{id}/review-status와 교수자 SessionReview 카드에서 승인·수정요청·반려 수동 판정을 저장/표시한다. CCD는 숨은 정답키로 남고 저장본에 점수로 노출하지 않는다. 임상팀 확정 루브릭 콘텐츠(level anchor, 가중치, 컷오프, 예시 답안), AI 채점 적용·calibration, 승인 후 잠금·재제출 정책, 재귀학습 데이터셋 approved 연계. doc1·doc4·doc5
C2 위기개입 프로토콜·생명유지서약·에스컬레이션 1차 배선 완료·임상 고도화 필요 실제 자해·자살 신호는 LLM/엔진 호출 전 중단하고 109 리소스와 conversation_stopped를 REST/SSE/voice 응답에 싣는다. crisis.risk_level은 상태머신 ideation_observed로 전달하고, escalate 시 app.safety_events detail 적재 및 교수자 대시보드 안전 알림 큐로 연결한다. 남은 것은 임상팀 콘텐츠: 비밀보장 예외고지→단계적 탐색→생명유지서약 스크립트, 실시간 push/메일 알림 정책, 위기탐색 누락 시 회기리뷰 감점 루브릭. doc1·doc5(핵심 시나리오)·doc4(IRB 전제)
C3 이론모드 2차 배선·학습자 명시 선택 UI 완료·CBT 콘텐츠 잔여 TurnContext/prepare_turn/sessions/voice/evaluator에 theory_mode가 전달되고, build_turn_messages도 인간중심·CBT·통합 이론 프레이밍을 엔진 메시지에 넣는다. 프론트는 persona.theory_target 기준 기본값을 잡되, 세션 시작 전 humanistic/cbt/integrative segmented control로 학습자가 명시 선택하고 POST /sessionstheory_mode로 전송한다. 임상팀이 확정한 CBT 단계 프롬프트 체인, 이론부합 채점 루브릭. 이번 UI는 임상 문안·루브릭·백엔드 enum을 확장하지 않았다. doc4(humanistic+CBT 필수)·doc2/doc5

High (4)

ID 현재상태 권고 근거
H1 계약 평가 KPI(자기효능감·기술숙련도·수련만족도 사전사후) 수집·입력·CSV/report 계산 2차 app.learner_prepost_measure, 학습자 본인용 GET/PUT /users/me/prepost-measures, SessionReview의 파일럿 증거 원장 카드가 3척도 pre/post 1~5 aggregate evidence를 저장·조회한다. app.services.phase3_kpi_exportscripts/export-phase3-kpi.py는 원장 row를 Phase 3 evidence root의 02-measures/prepost_measures.csv02-measures/kpi_report.json scaffold로 산출한다. participant id는 가명화하고, 3척도 paired normalized mean pre/post/delta, complete/missing pair를 계산한다. 2차에서는 phase3_kpi_contract.py가 KPI metric 이름·필수키·computed_prepost/design_pending status 값을 소유해 exporter/checker/test의 drift를 줄이고, 계산 가능한 pre/post evidence와 평가설계 전 미계산 KPI를 report 안에서 구분한다. 공식 문항 확정, 실험/통제군 배정, 추이 시각화, 통계검정 종류/alpha/결측 처리, 실제 20명 evidence와 steward/legal/IAA 검수. 현재 API/UI/export는 공식 효과성·성적·수료 판정이 아니라 파일럿 evidence 계산이다. (κ/ICC·환각률은 doc4 미명시 → 평가설계 확정.) doc4(20명 실험/통제군·단회기 50분·3척도 pre-post)
H2 턴별 fast-loop + 라이브 코칭 1차 가동·학습자 리뷰 3열 workbench 완료·골든셋 잔여 make_eval_hook이 submit/voice 생성 경로에 주입되고, stream은 _evaluate_stream_turn으로 fast-loop 평가를 붙인다. 결과는 feedback_scores, alternative_utterance 등 정규화 테이블에 적재·hydrate된다. 추가로 app/services/live_coach.py, POST/GET /sessions/{id}/live-coach, POST /kb/live-coach/source-packs/sync, app.live_coach_events, data/kb/live_coaching_workbook_0615.json, data/kb/live_coaching_sources/*.json을 연결해 워크북·DSM·공식 지침 요약 기반 코칭 아바타 말풍선·근거 모달·발화별 이력 오버레이와 RAG 증분 색인을 제공한다. app.services.source_pack_sync가 repo source pack의 active content_hash를 비교하고 변경 시 document version을 최신+1로 올린다. live turn은 프로세스 로컬 source pack snapshot을 재사용하지만, 관리자 sync/CLI는 refresh=True로 캐시를 비운 뒤 repo 파일을 다시 읽어 stale content_hash 비교를 막는다. 학습자 SessionReview 데스크톱은 요약/흐름, 축어록, 평가 rail의 3열 workbench와 하단 워크시트로 재배치했고, empty review는 2열 이하로 유지한다. 워크시트/pre-post/교수자 메모 입력과 발화 이동 버튼은 name/autocomplete/aria-label 및 공유 focus token으로 접근성 회귀 표면을 줄였다. 원천 축어록 few-shot 골든셋 적재, 임상팀 확정 루브릭과 source pack 임상 검수 상태 운영정책 보강. doc2·doc5(골드 포맷)
H3 임상팀 콘텐츠 입력 경로(페르소나 저작 CRUD) 2차 구현·원문 격리 정책 1차·항목형 목록 저작/프롬프트 검토 UI 완료·임상 검수 잔여 draft 생성·조회·편집·검수요청 API와 교수 콘솔 JSON 초안 패널은 연결됐다. persona_repository.py는 in-code SEED_PERSONAS(P1P3)와 data/personas/P4.jsonP7.jsonPersonaCard로 합쳐 materialize_seed_personas()와 seed fallback catalog에 포함한다. scripts/materialize-persona-seeds.py는 같은 seed manifest를 dry-run 기본으로 보고하고, --apply에서만 DB pool을 초기화한 뒤 기존 idempotent DB materializer를 호출한다. scripts/sync-persona-sources.py는 DB-backed dry-run/apply runner로 repo-managed source pack의 content_hash/document version을 비교한다. RAG 기반 draft 생성은 source/chunk evidence와 함께 persona-draft-rag@2026-06-28.1 prompt bundle id/version/hash를 engine metadata 및 draft source_provenance에 남긴다. POST /personas/sources는 raw 원문 hash-only 증거를 kb.raw_source_artifact에 따로 기록하고, sanitized 파생본만 evaluator-only RAG chunk로 색인한다. rag.index_document()sensitivity=3 또는 raw marker chunk를 DB 접근 전에 차단한다. app/persona_read_model.py는 catalog/review/draft/source/evidence DTO와 mapper를 route에서 분리해 OpenAPI schema 이름을 유지한다. PersonaStudio는 자동사고, 회기 시나리오, 말투 filler/verbal tic/nonverbal cue, 역린·금기 응답·금기어를 행 추가/삭제 UI로 편집하고, 저장 직전 빈 항목을 제거하되 기존 배열 schema를 유지한다. 프롬프트 탭은 raw JSON textarea 대신 L1 카드·인적 범주·임상 배경·말투·수치 파라미터·역린·회기 시나리오·추가 계약 섹션으로 같은 draft 데이터를 검토하게 한다. 루브릭·이론 콘텐츠 외부화, P4~P7 포함 임상팀 최종 검수/서면 evidence 확보, 암호화 blob/vault 기반 원문 실저장. doc3(R&R)·doc4(페르소나=전문가 산출물)
H4 PII 마스킹 한국어 로컬 휴리스틱 + optional ko recognizer adapter + 15-case fixture/schema 평가 harness + 온보딩·동의 게이트 잔여 Presidio language='en' 고정 한계를 보완하기 위해 정규식 폴백에 한국어 날짜·금액·행정구역 주소와 함께 이름/성명 라벨, 성씨+이름+조사/호칭, 대학교·학과·병원·센터 등 기관 suffix 기반 로컬 휴리스틱 마스킹을 추가했다. 66차에서는 제 이름은 김서연입니다, 보호자 이름은 박민수입니다, 저는 최하늘입니다 같은 자연 발화형 이름 라벨·자기소개 패턴을 추가하고 이름은 중요하지 않다 negative control로 오탐을 막았다. Presidio가 설치돼도 한국어 누락을 막기 위해 fallback을 후단에 한 번 더 태운다. 70차에서는 guardrail.mask_pii() 내부에 선택형 한국어 PII recognizer adapter 경계를 추가했다. adapter는 import-time hard dependency가 아니며 명시 등록 전에는 비활성이고, 실패해도 기존 regex fallback이 마지막 안전망으로 유지된다. fake adapter 테스트는 regex가 못 잡는 별명/기관 span을 [NAME]/[ORG]로 마스킹하고 같은 문장의 전화번호는 후단 regex가 [PHONE]으로 처리하는지, adapter 실패 시에도 fallback이 유지되는지 검증한다. 상담 생성(generate/stream), fast evaluator prompt, client turn text_masked에서 한국어 NAME/ORG raw 값이 남지 않도록 회귀화했다. app.services.pii_masking_eval, data/privacy/pii-masking-ko-fixtures.json, scripts/evaluate-pii-masking.py로 합성 fixture 15케이스를 NAME/ORG/PHONE/EMAIL/RRN/NUMID/DATE/MONEY/ADDR/negative-control 범위에서 entity recall·forbidden substring removal·unexpected entity violation으로 평가한다. data/privacy/pii-masking-eval-input.schema.jsondata/privacy/pii-masking-eval-report.schema.json은 source/category/severity metadata와 summary-only technical_dry_run 리포트 계약을 고정하며, 기본 CLI JSON은 masked_text/forbidden_remaining 원문 증거를 제외한다. 소속/안내/이름 NAME 오탐도 stopword로 보정했다. 외부 LLM 호출은 상담 생성(generate/stream)·fast/deep 평가 직후 audit.llm_call_log에 provider/model/token/cost/inference_geo/latency만 적재하도록 연결했고, prompt/completion 본문은 저장하지 않는다. 로컬 dev-login 실제 /turn smoke에서 audit.llm_call_log 3행 증가를 확인했다. app_user에 이름·소속·학과·학년/직위·연락처·주소/수령지·닉네임·자기소개·아바타 URL·약관/개인정보 동의 버전 필드를 추가했고, 로그인 직후 /onboarding 완료 전에는 역할 홈과 learner 회기 시작을 막는다. 아바타 이미지는 /users/me/avatar에서 MIME/시그니처/3MB 제한 후 파일 저장소에 두고 URL만 보관한다. 온보딩 저장 시 learner consent_at도 함께 세팅하며 auth E2E에서 신규 계정 온보딩→아바타 업로드→학습자 홈 이동을 검증했다. 실제 ko recognizer 모델/provider 선정, 운영 말뭉치 기반 오탐/미탐 평가, 미성년/guardian 및 법무 검토가 필요한 최종 서명 동의서·개인정보 처리방침·약관 evidence 확보. 공개 Google OAuth 실제 /turn proof는 별도 운영 게이트. doc1/2/5(실명·날짜·미성년·자살시도 다수)·doc4(IRB·개인정보)

Medium+ (6) — M1M3, X1X2, L1

ID 현재상태 권고
M1 비언어/준언어 임상 이벤트 캡처·태깅 4차 진행 1차에서 audio_ref/silence_ms/speech_rate/barge_in을 learner voice turn에 저장하고 리뷰 nonverbal 칩으로 파생했다. 2차에서는 app.turns.provider_events JSONBTurnRecord.provider_events를 추가해 WebSocket control/STT provider 이벤트를 allowlist·size limit 후 보존한다. 3차에서는 저장 전 sanitizer에서 내부 taxonomy event_type/category를 붙인다. 4차에서는 인증된 회기 리뷰 API가 sigh/cry/laugh/breath, prosody, background noise 계열만 한글 label/detail 칩으로 파생 노출한다. raw transcript/text payload, provider/source/raw type, 공개 공유 카드 노출은 제외한다. 실제 provider 기반 한숨·울음·억양 감지 연결, 장시간 마이크/WSS 실측, 리뷰 칩을 역량 지표로 해석할지에 대한 정책.
M2 다회기 종단 케이스 아크·교차회기 사례개념화 11차 구동 (persona_id, learner_id) 안정 case_profile upsert, 원자적 session_no, voice/REST/SSE recall cache 주입을 연결했다. 세션 종료 시 마스킹 축어록 기반 fallback session_summary.digest, case_profile.case_digest, rapport_trajectory, alliance_level을 갱신하고, 다음 회기 seed recall은 case_digest·직전 session_summary·client-visible non-contradicted pinned_fact를 함께 조립한다. 3차에서는 마스킹된 client-visible 발화에서 [NAME]/[ORG] identity와 명시적 상담 약속만 보수적으로 pinned_fact에 upsert한다. 4차에서는 pinned fact 삽입 또는 값 변경 시 pinned_fact_history에 append-only 이력을 남긴다. 5차에서는 명시적 상담 약속 철회/부정만 기존 non-locked agreement:counseling fact를 contradicted로 격리하고 history reason contradiction을 남긴다. 6차에서는 세션 종료 저장 성공 뒤 마스킹된 client-visible 내담자 발화만 app.turn_embedding에 BGE-M3 dense/sparse로 idempotent 색인한다. 7차에서는 REST submit/SSE stream의 턴 컨텍스트 조립 경계를 _prepare_turn_context()로 묶고, DB seed recall과 pinned fact가 다음 턴 EngineMessage L2/L4에 raw 이름 마스킹 상태로 주입되는 route-level 회귀를 추가했다. 8차에서는 SessionDigestInput/SessionDigestResult/SessionSummaryWrite로 종료 digest 입력·fallback 결과·DB write 인자 경계를 명시해 LLM worker 후보가 raw text, evaluator-only turn, 평가 payload, CCD, deterministic carry를 압축 prompt에 우회 주입하지 못하게 했다. 9차에서는 DigestQualityAssessment/SessionDigestWorkerOutcome로 local quality harness를 추가해 빈/짧은 digest, raw forbidden substring, 내부 평가·CCD·상태 marker, 잘못된 S{session_no}: prefix를 fallback 유지 대상으로 판정한다. 10차에서는 session_digest_worker.pyCompressionJob을 Node-compatible GenerateRequest/EngineMessage로 변환하고, 주입형 engine/audit 호출 뒤 quality gate 통과 결과만 session_summary.digest/compressed_by/token_countcase_profile.case_digest에 적용하는 one-shot 경계를 소유한다. 11차에서는 scripts/run-session-digest-worker.py dry-run/apply runner와 SESSION_DIGEST_WORKER_ENABLED=false 기본값의 세션 종료 background scheduler 골격을 붙였다. scheduler는 DB load/apply 때만 connection을 잡고 engine 호출은 transaction 밖에서 수행하며, compressed_by IS NULL loader/apply CAS로 재실행 race를 막는다. DB loader는 persisted fallback summary와 client-visible text_masked transcript만 재구성하며 raw text, evaluator-only turn, CCD, end_state는 prompt에 넣지 않는다. digest_pending은 CompressionJob 생성 여부를 알리는 비동기 압축 필요 신호로 유지한다. 같은 값 재확인은 history를 늘리지 않고, locked fact는 건드리지 않는다. 관계갈등·위기·임상 추론은 자동 pinning/모순 처리에서 제외한다. 관계·임상 fact 승격 기준, 실 provider 장시간 운영, 임상 골든셋 품질평가, 재압축, 접수면접→다회기 연속성·자기개념 진화 실증.
M3 SSO claim 매핑·식별자 안정성 1차 완료·운영 IdP 감사 미연결 Google/SAML/dev-login이 AUTH_EMAIL_COHORT_MAP·AUTH_DOMAIN_COHORT_MAP 및 SAML cohort claim을 cohort_ids로 전달하고, app_user.external_id는 provider subject(google:/saml:/dev:) 기반으로 저장한다. 운영 SAML 서명검증, 기관 claim schema/test tenant, deprovisioning audit은 아직 없다. 한신 IdP 확정 후 SAML 서명검증, claim→role/cohort/institution_user_id 매핑 표 실연동, role변경/삭제 audit, deprovisioning evidence.
X1 재귀학습·데이터셋 export 파이프라인 1차 구현 scripts/export-recursive-dataset.pyapp.services.dataset_export로 masked-text JSONL dry-run, PII scan, kappa/ICC 계산, approved export 게이트를 구현했다. 기본은 technical_dry_run이며 실제 승인 export·골든셋 승격은 데이터 steward/legal review와 IAA 통과가 필요하다. 파일럿 evidence에서 reviewer disposition, steward/legal 승인, gold annotation 라운드 적재 후 approved_for_recursive_learning_seed 승격 검증.
X2 AI API 비용 관측·예산 경고·평가 저비용 라우팅·evaluator cache 관측·일별 비용 추이·모델별 비용 검증 리포트 2차 완료 턴별 provider/model/tokens/cost 저장 경로와 GET /admin/usage, 관리자 비용 대시보드를 연결했다. ADMIN_USAGE_BUDGET_USD 기준 예산 상태(ok/warn/exceeded)도 응답/UI에 표시한다. EVALUATOR_FAST_MODEL/EVALUATOR_DEEP_MODEL 설정 시 fast/deep 평가 호출만 해당 모델 override로 gateway에 전달하고, 비워두면 기존 gateway default 라우팅을 유지한다. fast/deep evaluator structured 결과는 canonical request SHA-256 기반 인메모리 semantic cache로 재사용하며, 원문 prompt·completion은 저장하지 않고 성공 파싱 결과만 TTL/entry 제한 안에서 캐시한다. /admin/usage와 관리자 비용 카드가 cache enabled/entries/hits/misses/stores/evictions/requests/hit_rate와 일별 daily_cost 추이를 노출한다. app.services.usage_reportscripts/report-ai-usage.py는 같은 usage JSON에서 provider/model별 cost share, token share, cost/turn, cost/1k tokens, metered coverage, budget/cache warning을 산출한다. DB 미가용 dev는 runtime store fallback, prod는 fail-closed다. 자동 차단·한도 enforcement 정책.
L1 기술스택 신청서-구현 불일치 및 단기일정 산출물 압박 doc4 신청서 스택(Spring Boot 3/Node.js·TimescaleDB) vs 실제 FastAPI/Python 불일치, 20주 단기일정·9월 저작권 등재 압박. 소유자 결정으로 장기 교체 대상은 Node.js 우선, 현재 FastAPI 전면 재작성은 보류했다. 내부 전환 증거로 engine gateway 공유 계약, EngineClient.stream_packets() decode 경계, schema-backed golden fixture(engine_gateway_contract.v1.json/engine_gateway_schema.v1.json), Python import 없는 scripts/check-engine-gateway-contract.mjs Node.js conformance runner, gateway-default default-routing sentinel 정규화, structured_payload_from_response() 기반 structured/legacy JSON response parser, 브라우저-facing 세션 read-model 분리(app/session_read_model.py), 페르소나 DTO/mapper 분리(app/persona_read_model.py), 페르소나 draft generation 계약(app/persona_generation_contract.py), session evaluation write packet(SessionEvaluationWrite), stage 라벨/phase-key 정규화 SSOT(app/stage_contract.py)까지 고정했다. 신청서/저작권 등재 문서에 FastAPI 유지 사유와 계약 우선 Node 전환 계획을 반영하는 외부 거버넌스 증거. 내부 후보였던 H3 항목형 목록 저작 UI와 프롬프트 미리보기 de-JSON은 10차에서 완료.

X2 근거: doc3 회의록이 'AI API 비용'을 운영 리스크로 명시.


3. R&R — 누가 무엇을 소유하는가

원칙(doc3 회의록): 콘텐츠는 임상팀 소유, 코드는 "편집 가능 구조"만 선제 구축. 코드와 콘텐츠를 한 PR에 섞지 말 것 — 구조(스키마·폼·주입 경로)는 기술팀이 먼저 만들되, 그 안에 들어갈 임상 문안은 임상팀이 데이터로 채운다.

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

  • C1 4차 완료: caseWorksheet 응답 구조, 리뷰 화면 편집 UI, app.case_worksheet 저장/재조회 경로, 외부 루브릭 schema/loader/validation scaffold, 교수자 수동 워크시트 검수 상태 저장/표시. 워크시트 템플릿 key source는 CASE_WORKSHEET_SECTION_SPECS/case_worksheet_template_item_keys()로 명시했다. 후속은 임상팀 확정 루브릭 콘텐츠, AI 채점 보정, 승인 후 잠금·재제출 정책.
  • C2 1차 완료: 위기 신호는 엔진 전 중단, 109 안내, safety_events 적재, 교수자 알림 큐, ideation_observed 전달까지 배선했다. 후속은 임상 스크립트·서약 문안·감점 루브릭.
  • C3 2차 완료: theory_mode가 세션·평가·생성 프롬프트까지 흐르고, 학습자는 세션 시작 전 기존 3개 모드 중 하나를 명시 선택해 POST /sessions로 보낸다. 후속은 임상팀 CBT 체인·이론부합 루브릭.
  • H2 1차+라이브 코칭+리뷰 3열 workbench 완료: make_eval_hook과 stream 평가가 턴 파이프라인에 붙고 정규화 테이블로 적재·복원된다. 대안발화도 app.alternative_utterance로 정규화한다. 라이브 코칭은 0615 워크북·DSM·공식 지침 요약/RAG 근거로 코칭 아바타 말풍선·근거 모달·발화별 이력 오버레이까지 연결했다. POST /kb/live-coach/source-packs/sync는 공용 source pack sync service를 통해 evaluator 전용 RAG에 증분 색인하고, hash 변경 시 document version을 최신+1로 올린다. 관리자 sync/CLI는 source pack manifest 생성 전 process-local cache를 refresh해 현재 repo JSON 기준으로 비교한다. 학습자 SessionReview 데스크톱은 요약/흐름, 축어록, 평가 rail의 3열 workbench와 하단 워크시트로 재배치했고, 교수자/모바일 레이아웃은 기존 규칙을 유지한다. 후속은 골든셋·임상팀 루브릭·source pack 임상 검수 상태 운영.
  • H3 10차 완료: 페르소나 저작 CRUD(draft→review), P4~P7 저장소 JSON 로드, RAG source 기반 draft generation, prompt bundle id/version/hash provenance와 seed/version materializer runner가 붙었다. seed runner는 dry-run/JSON manifest를 제공하고, --apply에서만 DB pool을 초기화해 기존 materializer를 호출한다. repo-managed source pack runner는 DB-backed dry-run/apply를 제공하며 active content_hash가 바뀐 문서만 최신 version+1로 sync한다. kb.raw_source_artifact hash-only 레코드와 rag.index_document() raw/sensitivity=3 fail-closed guard를 추가해 raw 원문이 kb.chunk/embedding/FTS로 들어가지 않게 했고, app/persona_read_model.py로 persona DTO/mapper 경계를 분리했다. PersonaStudio의 자동사고·회기 시나리오·말투 목록·역린/금기 목록은 행 추가/삭제 UI로 바꾸고 기존 배열 payload 계약을 유지한다. 이번 패스에서 프롬프트 미리보기 raw JSON textarea를 라벨형 검토 섹션으로 교체했다. 후속은 루브릭·이론 콘텐츠 외부화, 임상팀 최종 검수 evidence, 암호화 blob/vault 기반 원문 실저장.
  • H3 11차 / L1 계약 보강 완료: app/persona_generation_contract.py가 페르소나 draft structured schema, prompt bundle id/version/hash, GenerateResponse payload extraction, generated draft defaults/coercion을 소유한다. routes/personas.py는 auth, RAG evidence, engine invocation, provenance assembly, HTTP error mapping을 유지한다. 이어서 evaluator/live-coach의 로컬 structured payload alias를 제거하고 structured_payload_from_response()를 직접 호출하게 했으며, SessionEvaluationWriteapp.session_evaluation 저장 packet을 소유한다. 최신 L1 검증은 persona contract+review 39 passed, gateway contract 27 passed, backend focused 120 passed, Node conformance OK, npm run check:api-types, npm run typecheck.
  • H4(부분)·X1·X2: 한국어 날짜/금액/주소 및 이름/기관 로컬 휴리스틱 마스킹, 15-case 합성 fixture 평가 harness와 input/report schema(summary-only technical_dry_run report), 자연 발화형 이름 라벨·자기소개 마스킹 보강, optional ko recognizer adapter 인터페이스와 fake/failure 회귀, 외부 LLM 호출 metadata-only audit.llm_call_log 적재 경로, 학습자 동의 수락/철회/회기 시작 하드게이트 골격은 완료했다. 실제 ko recognizer 모델/provider 선정, 운영 말뭉치 기반 평가, guardian/legal 서명 evidence는 후속이다. dry-run JSONL export·PII scan·IAA 계산 1차도 완료했고 ds.* write는 --write-dataset 명시 시에만 수행한다. X2 비용 관측·예산 경고, evaluator fast/deep 모델 override, evaluator semantic cache, 운영 hit-rate 관측, 일별 비용 추이, 모델별 비용 검증 리포트는 완료했고 자동 차단·한도 enforcement 정책은 후속. M1은 provider_events 보존 슬롯, 내부 taxonomy, 인증 리뷰용 제한 파생 칩까지 완료했고, M2는 보수적 identity/agreement pinned_fact 자동 실적재, append-only history, 명시적 상담 약속 철회 contradiction, episodic embedding writer, 다음 턴 EngineMessage 주입 회귀, digest contract/local quality harness, one-shot worker/runner/default-off scheduler/CAS 경계까지 완료했다. L1은 Node.js conformance runner, gateway-default default-routing sentinel 정규화, session/persona read-model 분리까지 완료했다. 실제 provider 기반 한숨·울음 감지는 후속.

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

  • 임상팀(구훈정·어유경) 산출물: C1 채점 루브릭·항목 확정, C3 CBT 이론 콘텐츠·프롬프트 체인, C2 위기 스크립트·서약 문안, H2 골든셋 코딩·라이브 코칭 루브릭 검수. DSM/공식 지침/논문은 사용 허가 확인 기준으로 KB 확장 가능하며, 각 source pack은 version/citation/임상 검수 상태를 남긴다. → 코드는 구조를 선제 구축하되 임상 문안과 평가기준은 외부 정의로 받는다.
  • 소유자 평가설계 결정: H1 실험/통제군 배정·3척도 문항·50분 흐름. κ/ICC·환각률 목표는 doc4 미명시 → 평가설계 문서 확정.
  • 기관(한신 IT) 의존: M3 SSO IdP 프로토콜·test tenant·claim 스키마, SAML 인증서, deprovisioning 거버넌스 증거.
  • 거버넌스 증거: L1 스택 정합성 처리 방향은 Node.js 우선 교체 가능성으로 결정됨. 남은 것은 FastAPI 유지 사유와 계약 우선 전환 계획의 외부 제출/저작권 등재 문서 반영, IP 협의 증거.

4. 작업 시작 절차 (체크리스트)

특정 갭(예: C2)에 착수하기 전에:

  1. SSOT 확인: docs/dev_dashboard.html의 "원천문서 갭 분석" 섹션에서 해당 항목의 최신 상태/우선순위를 본다.
  2. 상세 근거 확인: docs/ops/source-docs-gap-analysis-2026-06-26.md의 동일 ID 항목에서 근거·권고·소유 구분(A/B)을 본다.
  3. 코드 1차 재확인: (분석) 표기 항목은 착수 전 grep으로 현재상태를 직접 재확인한다(아래 예시).
  4. 소유 구분 판정: 콘텐츠가 필요한가? → 임상팀 핸드오프 선행. 구조/배선만인가? → 즉시 착수(섹션 3-A).
  5. 검증 게이트 통과: 변경 후 표준 테스트를 돌린다(아래 명령).

코드 재확인 grep 예시 (저장소 루트 D:/workspace/vignette)

# C1: 사례개념화 워크시트 저장형 구조와 잔여 채점/검수 경로 확인
rg -n "caseWorksheet|ReviewCaseWorksheet|case_worksheet|save_session_review_worksheet|사례개념화 워크시트|인지삼제|4사분면" apps infra

# C2: escalate 시 safety_events 적재 여부
rg -n "safety_events|escalate|ideation_observed" apps/api/app/services/orchestrator.py

# C3: 이론모드 스레딩과 생성 프롬프트 주입 확인
rg -n "theory_mode|THEORY_MODE_GUIDANCE|sessionApi.start\\(personaCode" apps

# H2: eval_hook 정의와 주입
rg -n "make_eval_hook" apps/api/app

# H3: 페르소나 seed/materialize 로드 경로
rg -n "SEED_PERSONAS|load_file_personas|built_in_personas|materialize_seed_personas" apps/api/app/persona_repository.py
rg -n "materialize_seed_personas|init_pool|close_pool|--apply|--json" scripts/materialize-persona-seeds.py

검증 명령 (변경 후)

# 백엔드 (작업 디렉터리 apps/api)
python -m pytest app/ -q            # 백엔드 기준선 178 pass
python -m pytest engine_gateway/ -q # 게이트웨이 현재 27 pass

# 프론트 (작업 디렉터리 apps/web)
npm run typecheck
npm run build                       # vite
npm run e2e                         # Playwright — web+api+DB 스택 필요

로컬 기동: API는 apps/api에서 python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload(pydantic-settings가 apps/api/.env 자동 로드, DB 미가용 시 in-memory degraded 폴백). 웹은 apps/web에서 npm run dev(http://localhost:5173, /api→127.0.0.1:8000 프록시). AI 턴 생성은 ENGINE_MODE=claude_cli일 때 engine_gateway가 포트 9099에 떠 있어야 한다.


5. 판독 한계 (정직성)

  • 핵심 축어록 2단 표(doc5 상1~63, doc2 3회기 표)는 txt 추출 시 일부 누락 — PDF 시각 판독이 1차 근거.
  • OCR 잔재·오탈자 존재(doc1·doc5). 의미는 시각 보정했으나 일부 표현 불확실.
  • doc4 κ/ICC·환각률은 신청서 본문 미명시 — 계약 확정 지표로 단정 금지.
  • doc4/doc3 행정 불일치(참여교수 1명 vs 2명, 서식 연도 '2025' 오기, 연구책임자 표기 불일치, 트웬티온스 성명 공란).
  • '현재상태'는 grep/코드 사실 기반 적대적 비평 인용에서 시작했으나, C1·C2·C3·H1 pre/post 원장·KPI export·metric status contract·H2·H3·M1 provider_events 보존/taxonomy/인증 리뷰 파생 칩·M2 case memory/pinned_fact/history/명시철회 contradiction/episodic embedding writer/다음턴 주입회귀/digest contract/local quality harness/one-shot worker+runner+default-off scheduler boundary·M3, H4 로컬 마스킹/optional ko adapter/fixture 평가/감사/온보딩 경로, X1 dry-run export, X2 비용 관측·evaluator routing/cache/hit-rate 관측·모델별 비용 리포트, L1 engine gateway contract/golden/schema/Node conformance runner/default-routing sentinel/structured payload parser/session read-model/persona read-model/persona generation contract/session evaluation write packet 분리는 구현 후 재검증 완료 기준이다. H1은 파일럿 evidence 계산과 report 계약까지이며, 공식 효과성 판정·통계해석·20명 evidence는 완료로 보지 않는다. M2는 fallback digest, digest_pending 응답 계약, LLM 후보 local quality harness, accepted-only one-shot worker/runner/default-off scheduler 경계까지이며, 실 provider 장시간 운영·임상 골든셋 품질평가·재압축은 완료로 보지 않는다. 다만 H4의 실제 ko recognizer 모델/provider 선정과 운영 corpus 평가, guardian/legal evidence, 공개 OAuth /turn proof, M1 실제 provider 기반 한숨·울음 감지는 여전히 게이트로 남아 있다. L1 외부 거버넌스는 FastAPI 유지 사유와 Node 전환 계획의 제출/등재 증거가 남아 있다.

변경 이력

  • 2026-06-29: L1 gateway-default default-routing sentinel, structured_payload_from_response(), persona generation contract, SessionEvaluationWrite와 gateway contract 검증 기준 반영.
  • 2026-06-29: scripts/check-dev-dashboard-ssot.py dashboard SSOT drift gate와 M2 30/87 검증 수치 guard 반영.
  • 2026-06-28: M2 8차 digest contract 경계와 focused 74 passed 검증 기준 반영.
  • 2026-06-29: M2 9차 local digest quality harness와 test_session_memory.py 20 passed 검증 기준 반영.
  • 2026-06-29: M2 11차 one-shot digest worker runner/default-off scheduler/CAS boundary와 focused 30 passed 및 주변 회귀 87 passed 검증 기준 반영.
  • 2026-06-28: H1 2차 KPI metric status contract와 focused 10 passed 검증 기준 반영.
  • 2026-06-28: H4 optional ko recognizer adapter 경계와 focused 47 passed 검증 기준 반영.
  • 2026-06-26: 초판. docs/ops/source-docs-gap-analysis-2026-06-26.md와 SSOT 대시보드 "원천문서 갭 분석" 섹션을 요약·인덱스화.