112차 적용(2026-07-01): 교수자 회기 리뷰 데스크톱에서 overview/transcript가 여러 CSS Grid row를 가로질러 오른쪽 검토 rail 높이를 나눠 먹으며 중앙에 큰 빈 row가 생기던 문제를 제거했다. 1181px 이상 교수자 리뷰는 main column + review rail 2열 wrapper로 분리하고, main 내부는 요약 전체폭, 차트/회기 흐름 2열, 축어록 전체폭으로 배치해 서로 다른 rail 높이가 빈공간을 만들지 않게 했다. 회귀 방지로 layout-visual-gate.spec.ts에 교수자 리뷰 폭별 dead vertical gap 검증을 추가했다. 검증: npm run typecheck, npm run build, session-review desktop 8 passed, layout-visual-gate 10 passed, session-layout desktop/mobile 8 passed.
113차 적용(2026-07-01): 학습자 /learn/practice 페르소나 리스트가 긴 한글 주호소 요약에서 카드 내부를 클립하던 문제를 수정했다. .lh-list-pane의 viewport 고정 높이와 내부 스크롤을 풀고, .lh-personas/.lh-persona가 콘텐츠 높이를 그대로 만들게 했으며, .lh-persona__summary 3줄 clamp를 제거했다. learner.spec.ts에는 각 페르소나 카드의 summary/body/card scroll overflow가 0인지 재는 regression guard를 추가했다. 검증: npm run typecheck, npm run build, 브라우저 rect smoke 1095px/1440px에서 카드 overflow 0 및 문서 가로 overflow 0. 현재 로컬 127.0.0.1:8000/health가 timeout이라 real API 기반 전체 learner.spec.ts는 이번 패스에서 미실행.
114차 적용(2026-07-01): 회기 종료 후 background deep 평가가 실제 durable DB row로 저장되는지 fixture 없이 검증했다. _schedule_session_evaluation()은 생성한 task를 반환하고 done callback에서 crash/cancel을 로그로 관찰하며, 평가 결과·timeout/error 저장이 durable store에 닿지 않으면 명시 error 로그를 남긴다. 교수자 명시 재평가 API도 평가 산출물이 생성됐지만 저장 실패하면 503으로 표면화한다. GET /eval/sessions/{id}/evaluation은 status/error/durable을 노출해 캐시 착시와 DB 저장 증거를 구분한다. 새 DB-backed E2E는 학습자 세션 생성→턴→종료→teacher 로그인→/eval/.../evaluation polling→교수자 리뷰 UI 평가 완료까지 실제 API/DB/엔진으로 확인한다. 검증: API 전체 309 passed, npm run check:api-types, npm run typecheck, PLAYWRIGHT_PORT=5205 npx playwright test e2e/session-persistence.spec.ts --project=chromium-single-run --workers=1 7 passed, PLAYWRIGHT_PORT=5203 npx playwright test e2e/session-review.spec.ts --project=chromium-desktop --project=chromium-mobile --workers=1 16 passed, 현재 Playwright 수집 기준 162 tests in 18 files.
-
115차 적용(2026-07-01): 교수자 학생 분석을 /teach 대시보드에서 분리해 좌측 메뉴의 /teach/analysis 전용 작업면으로 이동했다. 교수 콘솔은 검토 큐·위기 알림·페르소나 검수·최근 회기 triage만 맡고, 학생 분석은 학습자 목록 레일, 사용자별 추이, 단계 분포, 전체 회기 타임라인, 회기 리뷰 드릴다운 구조를 맡는다. 회귀 방지로 teacher.spec.ts는 콘솔에 분석 패널이 없고 메뉴를 통해 학생 분석 페이지로 이동하는지 확인하며, layout-visual-gate.spec.ts는 학생 분석 페이지를 7개 폭에서 별도 캡처·검사한다. 검증: npm run typecheck, npm run build, npm run check:api-types, PLAYWRIGHT_PORT=5211 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 9 passed, PLAYWRIGHT_PORT=5214 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1 11 passed, SSOT checker PASS, 현재 Playwright 수집 기준 163 tests / 18 files.
+
115차 적용(2026-07-01): 교수자 학생 분석을 /teach 대시보드에서 분리해 좌측 메뉴의 /teach/analysis 전용 작업면으로 이동했다. 교수 콘솔은 검토 큐·위기 알림·페르소나 검수·최근 회기 triage만 맡고, 학생 분석은 전체 학습자 검색 테이블을 먼저 보여준다. 각 학습자는 한 줄 행으로 표시하고, 우측 펼침 버튼은 행 아래에 미니 추이·기법 태그·최근 기록을 확장한다. 학습자 이름 또는 상세 보기 버튼은 ?learner= 상세 드릴다운으로 이동하며, 상세 화면은 추이·전체 회기·단계 분석 탭으로 선택 학습자의 전체 회기 이력을 나눈다. 회귀 방지로 teacher.spec.ts는 콘솔에 분석 패널이 없고 메뉴를 통해 학생 분석 페이지로 이동한 뒤 검색·행 펼침·상세 진입·전체 회기 탭을 확인하며, layout-visual-gate.spec.ts는 학생 분석 목록/상세 화면을 7개 폭에서 별도 캡처·검사한다. 검증: npm run typecheck, npm run build, npm run check:api-types, PLAYWRIGHT_PORT=5215 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 9 passed, PLAYWRIGHT_PORT=5217 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1 12 passed, 현재 Playwright 수집 기준 166 tests / 18 files.
116차 적용(2026-07-01): 원천문서 갭 E2E 목표에 맞춰 C1/C2 silent failure를 추가로 닫았다. C1은 학습자가 저장한 사례개념화 워크시트가 app.case_worksheet를 거쳐 교수자 검토 화면 read-only 값으로 복원되고, 교수자 수정요청 검수 메모가 teacherReview.worksheetStatus/worksheetNote로 재조회되는지 실제 브라우저/API/DB E2E로 고정했다. C2는 app.safety_events가 runtime bootstrap/healthcheck에서 빠져 DB 정상처럼 보일 수 있던 구멍과, jsonb codec 위에 이미 직렬화한 문자열을 넘겨 detail이 JSON string으로 저장되던 구멍을 수정했다. record_safety_event()는 RLS용 ai_context=true로 저장하고, alert list 실패는 non-dev에서 fail-closed한다. 검증: python -X utf8 -m pytest -p no:cacheprovider app/test_session_turn_persistence.py app/test_teacher_dashboard.py app/test_runtime_policy.py -q 59 passed, PLAYWRIGHT_PORT=5228 npx playwright test e2e/session-persistence.spec.ts --project=chromium-single-run --workers=1 --grep "case worksheet|crisis safety" 2 passed, 현재 Playwright 수집 기준 166 tests in 18 files.
20차 적용(2026-06-28): 신규 Google/SAML 사용자는 account_status=pending으로 시작하고 승인 전에는 /pending 안내 화면만 본다. yunchan@twentyoz.kr는 슈퍼 관리자 allowlist로 admin+approved를 받으며, /admin/users는 가입 승인 탭에서 pending 계정을 승인 또는 보류 처리한다.
21차 적용(2026-06-28): 관리자 페이지 진입권을 기본 역할과 분리해 app_user.admin_access로 저장한다. AUTH_SUPER_ADMIN_EMAILS 기본값은 yunchan@twentyoz.kr, hoonjungkoo@hs.ac.kr이며, 슈퍼 관리자는 학습자·교수자·관리자 공간 전환과 관리자 권한 부여/회수를 할 수 있다. 학생·교수 계정도 admin_access=true면 우측 상단 관리자 진입이 노출된다. 구성 슈퍼 관리자의 권한 회수와 계정 비활성화는 차단한다.
@@ -670,8 +670,8 @@
현재
PDF(9·16·18쪽): 자해·자살 감지 시 대화 중단 + 자살예방상담 109 안내 + 지도교수 자동 알림, 안전은 LLM 밖 별도 CrisisGate. 구현: CRISIS_HOTLINE_NUMBER=109, TurnResponse.crisis_resource/conversation_stopped, REST·SSE·voice 경로의 엔진 호출 전 중단, app.safety_events detail 적재, 교수자 대시보드 안전 알림 큐.
검증
pytest app/test_session_turn_persistence.py app/test_voice_ws.py -q 20 passed, 안전 이벤트 DB insert payload 테스트 포함. pytest app/test_teacher_dashboard.py app/test_session_turn_persistence.py app/test_voice_ws.py -q 21 passed.
잔여
비밀보장 예외고지·생명유지서약 등 임상 문안, 실시간 push/메일 알림, 지역 자원 확장, 운영 정책 문구는 소유자·임상팀 확정 필요. 현재 교수자 알림은 safety_events 기반 대시보드 큐다.
-
-
현재
TeacherDashboardResponse.learner_growth와 GET /teacher/learners/{learner_id}/analysis가 턴별 fast-loop 평가의 appropriateness, rapport_signal, 기법 태그를 학습자별로 집계한다. /teach는 검토 큐·위기 알림·페르소나 검수·최근 회기 triage만 맡고, /teach/analysis는 학습자 목록 레일, 회기별 막대 추이, 평균 라포, 변화폭, 단계 분포, 전체 회기 타임라인을 표시한다. 평가가 없는 회기는 "평가 부족"으로 남겨 가짜 곡선을 만들지 않는다. 회기 행은 /teach/session/{id}/review로 진입해 같은 회기 리뷰를 교수자 읽기 전용으로 열고, 워크시트는 학습자 제출물 수정 없이 검토 전용으로 표시한다.
검증
pytest app/test_teacher_dashboard.py app/test_session_turn_persistence.py app/test_voice_ws.py -q 21 passed, pytest app/test_rbac_idor.py app/test_teacher_dashboard.py -q 9 passed, npm run check:api-types, npm run typecheck, npm run build passed. npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 4 passed.
TeacherDashboardResponse.learner_growth와 GET /teacher/learners/{learner_id}/analysis가 턴별 fast-loop 평가의 appropriateness, rapport_signal, 기법 태그를 학습자별로 집계한다. /teach는 검토 큐·위기 알림·페르소나 검수·최근 회기 triage만 맡고, /teach/analysis는 검색 가능한 1행 학습자 테이블을 먼저 보여준다. 우측 펼침 버튼은 행 아래에 회기별 미니 추이, 평균 라포, 변화폭, 기법 태그, 최근 기록을 확장하고, 이름 또는 상세 보기 버튼은 ?learner= 상세 화면으로 들어간다. 상세 화면은 추이·전체 회기·단계 분석 탭으로 나뉘며, 회기 행은 /teach/session/{id}/review로 진입해 같은 회기 리뷰를 교수자 읽기 전용으로 연다. 평가가 없는 회기는 "평가 부족"으로 남겨 가짜 곡선을 만들지 않고, 워크시트는 학습자 제출물 수정 없이 검토 전용으로 표시한다.
검증
python -X utf8 -m pytest -p no:cacheprovider app/test_teacher_dashboard.py -q 6 passed, npm run check:api-types, npm run typecheck, npm run build passed. PLAYWRIGHT_PORT=5215 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 9 passed, PLAYWRIGHT_PORT=5217 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1 12 passed.
ManagedUserUpsertInput owns managed-user create/reactivate inputs; create_session(), admin user create, and direct auth regression calls no longer pass long keyword bags. ManagedUserMemoryInput remains DB→memory fallback/store sync, and ManagedUserPatch remains partial profile/admin update. Focused backend 103 passed; API type drift check passed.
real crisis stops before engine, returns 109 resource, and DB insert uses ai_context=true. db.healthcheck() now requires app.safety_events; alert detail handles legacy double-encoded JSON string rows; full browser+API+DB E2E verifies safety_events reaches the DB-backed teacher safety queue with resource 109.
-
Professor review workflow
python -X utf8 -m pytest -p no:cacheprovider app/test_teacher_dashboard.py -q / PLAYWRIGHT_PORT=5211 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 / PLAYWRIGHT_PORT=5214 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1 / npm run check:api-types / npm run typecheck / npm run build
5 backend passed + 9 E2E passed + strict visual gate 11 passed; /teach now keeps only triage queues, and /teach/analysis returns a selected learner's full session timeline, unrestricted trend points, stage breakdown, and review counts in a separate student analysis page.
+
Professor review workflow
python -X utf8 -m pytest -p no:cacheprovider app/test_teacher_dashboard.py -q / PLAYWRIGHT_PORT=5215 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1 / PLAYWRIGHT_PORT=5217 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1 / npm run check:api-types / npm run typecheck / npm run build
6 backend passed + 9 E2E passed + strict visual gate 12 passed; /teach now keeps only triage queues, and /teach/analysis starts with a searchable one-row-per-learner table, right-side row expansion, and ?learner= detail tabs for full session timeline, unrestricted trend points, stage breakdown, and review counts.
59 backend passed; shared session_metrics now prefers rehydrated label_ko for technique labels while preserving label/name/id/code fallback. alternative_utterances string and text/suggestion dict inputs are pinned before any future evaluator adapter extraction.
Teacher review status
pytest app/test_teacher_dashboard.py app/test_rbac_idor.py app/test_learner_dashboard.py -q / npm run typecheck / npm run build / teacher.spec.ts
12 backend passed + 4 E2E passed; app.session_review_status, teacher dashboard review_status/review_note/reviewed_at, worksheet worksheet_status/worksheet_note/worksheet_reviewed_at, and PUT /teacher/sessions/{session_id}/review-status are documented. 검토 큐 visible 회귀와 교수자 전용 review grid 영역도 테스트로 고정했다.
PLAYWRIGHT_PORT=5205 npx playwright test e2e/session-persistence.spec.ts --project=chromium-single-run --workers=1
7 passed; 기존 direct /turn real API 저장 검증에 더해 실제 Session UI가 openSessionStream()으로 POST /sessions/{id}/stream을 호출하고, stream 완료 후 DB-backed /review가 learner/client 축어록을 반환하는지 확인한다. 추가로 코칭 모드에서 POST /live-coach 성공 뒤 DB-backed GET /live-coach 이력과 재로딩 후 학습자 발화의 C 마커가 유지되는지 확인하고, voice WS stt_result 및 실제 Session 마이크 UI 생성 비언어 메타가 DB-backed review nonverbal로 파생되는지도 고정한다. 같은 spec은 Phase 3 pre/post 저장과 세션 종료 background deep 평가의 durable DB row까지 검증한다. db/engine health가 false면 skip하고, stream/live-coach/evaluation 503/error는 실패로 취급한다.
eval route 5 passed, focused backend 39 passed. 수동 session 재평가는 persona 기본 theory_target보다 학습자가 선택한 session theory_mode를 우선하고, turn 재평가도 TurnContext.theory_mode에 같은 값을 전달한다.
Crisis safety gate UI
PLAYWRIGHT_PORT=5193 npx playwright test e2e/session-mvp.spec.ts --project=chromium-single-run --workers=1
2 passed; mock SSE safety + done.conversation_stopped에서 안전 자원 109와 입력 disabled가 유지되고, 빈 client reply를 내담자 응답 없음으로 덮지 않으며 live-coach를 호출하지 않는지 검증한다.
-
Persona/session review UI E2E
PLAYWRIGHT_PORT=5211 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1
9 passed; teacher approves pending persona, opens pending/recent review detail, and reaches the separate student analysis page from the menu before switching full learner timelines.
+
Persona/session review UI E2E
PLAYWRIGHT_PORT=5215 npx playwright test e2e/teacher.spec.ts --project=chromium-single-run --workers=1
9 passed; teacher approves pending persona, opens pending/recent review detail, reaches the separate student analysis page from the menu, searches the learner table, expands a learner row, and drills into the full learner timeline tab.
Voice UI synthetic E2E
npx playwright test e2e/voice-success.spec.ts --project=chromium-single-run
2 passed; direct WS cascade plus Session mic button path with synthetic browser audio and Web Audio playback under blocked media-element autoplay
PLAYWRIGHT_PORT=5214 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1
11 passed; 11 screens × 7 widths(390/720/861/900/1024/1280/1440), horizontal overflow 0 + control clip 0, 77 full-page screenshots. 학생 분석 전용 화면과 빈 회기리뷰 fixture 포함.
+
Strict layout visual gate
PLAYWRIGHT_PORT=5217 npx playwright test e2e/layout-visual-gate.spec.ts --project=chromium-single-run --workers=1
12 passed; 12 screens × 7 widths(390/720/861/900/1024/1280/1440), horizontal overflow 0 + control clip 0, 84 full-page screenshots. 학생 분석 목록 테이블/상세 화면과 빈 회기리뷰 fixture 포함.