vignette/docs/ops/outcome-os-self-directed-learning-loop-ui-evidence-2026-08-07.md
Yun Chan 16e791e044 G0~G8 성과·동맹 측정 OS 작업 일괄 고정
8월 7일까지 워킹트리에만 남아 있던 미커밋 작업을 커밋한다. 여러 사본
폴더(worktree·clone)에 흩어져 있던 중간 스냅샷을 정리하기 전에 원본을
git 이력으로 고정하는 것이 목적이다.

- contracts/routes/services: measurement, outcome_trajectory, rupture_repair,
  deliberate_practice, calibration_transfer, supervision_research,
  multimodal_alliance, continuous_improvement 계열 신규 모듈과 테스트
- infra/db/init: 07~16 마이그레이션(측정 기반~calibration transfer 실행)
- apps/web: 세션 리뷰 카드·관리 화면·E2E 스펙 추가
- docs/ops: G0~G8 라이브 통합·배포·롤백 증거 문서와 evidence JSON/PNG
- scripts: smoke·ledger·릴리스 에이전트·NAS 프리뷰 운영 스크립트

engine.public 로그 .bak과 apps/web/test-results 산출물은 커밋에서 제외했다.
2026-08-08 01:30:53 +09:00

92 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# 학생 자기주도 전체 루프 UI 증거 — 2026-08-07
## 결론
실제 `apps/web/src` 제품 화면에서 학습자 홈의 목표 추천부터 페르소나 선택, 회기 목표 설정,
텍스트 회기 진행, 회기 종료와 리뷰, G4 처방 카드, 처방을 이어받은 새 회기 시작까지 하나의
브라우저 상태 흐름으로 연결했다. 데스크톱과 모바일 각각 1회, 합계 **2/2 passed**다.
이 증거는 로그인 없는 결정론 **route fixture UI 계약**이다. `/api/**`를 먼저 404로 닫고 테스트가
소유한 경로만 응답하므로 실제 API나 개발 DB를 사용하지 않는다. 실제 PostgreSQL production caller가
ready 평가와 durable turn에서 G4 처방 원장을 만드는 증거는
`outcome-os-g4-g5-production-caller-evidence-2026-08-07.md`가 별도로 소유한다. 두 증거를 합쳐
“브라우저 전체 루프가 실 DB에서 통과했다”고 주장하지 않는다.
## 검증한 제품 흐름
1. `/learn`에서 첫 회기 AI 코치와 `난도 확장 검토` 추천을 확인한다.
2. `연습 시작하기`로 `/learn/practice`에 진입해 P1을 고른다.
3. `/learn/session/P1`에서 인간중심 모드와 라포·탐색·개입 목표를 선택한다.
4. 실제 `Session.tsx` 활성 화면에서 텍스트 발화를 보내고 SSE 내담자 응답과 탐색 단계 전환을 확인한다.
5. 회기를 종료하고 `/review`에서 저장 축어록 기반 평가 요약과 G4 공감적 반영 처방을 확인한다.
6. 키보드 Enter로 `이 처방으로 연습 시작`을 실행한다.
7. 학습 홈과 새 회기 사전 설정에서 원본 회기 출처, 사용자용 판정 기준, 익숙한 장면, replay 모드가
보존되는지 확인한다. 원본 UUID와 내부 criterion/counterevidence 키는 화면에 노출하지 않는다.
8. 새 회기를 시작한 뒤 URL의 typed launch intent, 두 번째 시작 요청, 활성 화면의
`data-practice-mode="replay"`가 유지되는지 확인한다.
## Fixture 경계
- 실제 제품 코드: `LearnerHome.tsx`, `Session.tsx`, `SessionReview.tsx`, 제품 라우터와 CSS를 브라우저에서 실행한다.
- fixture 소유 API: `auth/me`, `personas`, `sessions` 목록·대시보드·시작·상세·stream·end·review,
`practice/learners/me`, pre/post measure, alliance pulse, live coach, voice health다.
- 소유하지 않은 모든 `/api/**`: fixture 404. 실 API로 조용히 폴백하지 않는다.
- 인증: `auth/me` fixture만 사용한다. 실제 사용자 로그인이나 저장된 세션을 사용하지 않는다.
- 음성: voice health를 unavailable로 고정한다. 물리 마이크를 열거나 장치를 열거하지 않는다.
- 데이터: 화면의 `source=database` 페르소나 표시는 API 계약값을 재현한 fixture 필드일 뿐 실 DB 증거가 아니다.
## 자동 검증
```powershell
cd apps/web
npx playwright test e2e/self-directed-learning-loop.spec.ts `
--project=chromium-desktop --project=chromium-mobile --workers=1 --reporter=dot
# 2 passed (18.8s)
npm run typecheck
# passed
```
테스트는 각 단계에서 페이지 가로 overflow 0, 홈 핵심 CTA 44px 이상·텍스트 대비 4.5:1 이상,
처방 CTA 키보드 실행, 시작 요청 payload와 launch intent 구조를 단언한다. 자동화 과정에서 홈
`연습 시작하기`가 40px로 렌더되는 결함을 발견해 `learner-home.css`의 최소 높이를 44px로 올렸다.
리뷰·학습 홈·사전 설정에서는 `criterion.reflect-and-check`, `unseen_transfer_not_verified`, 원본 회기
UUID, `humanistic, cbt`가 보이지 않고 각각 사용자용 한국어 기준·근거·출처·이론명으로 표시되는지도
금지 문자열과 허용 문자열을 함께 단언한다.
## 데스크톱·모바일 시각 QA
직접 확인한 고정 캡처:
- `evidence/self-directed-loop-home-chromium-desktop-2026-08-07.png`
- `evidence/self-directed-loop-home-chromium-mobile-2026-08-07.png`
- `evidence/self-directed-loop-active-session-chromium-desktop-2026-08-07.png`
- `evidence/self-directed-loop-active-session-chromium-mobile-2026-08-07.png`
- `evidence/self-directed-loop-active-session-320x568-chromium-mobile-2026-08-07.png`
- `evidence/self-directed-loop-review-prescription-chromium-desktop-2026-08-07.png`
- `evidence/self-directed-loop-review-prescription-chromium-mobile-2026-08-07.png`
- `evidence/self-directed-loop-repractice-prestart-chromium-desktop-2026-08-07.png`
- `evidence/self-directed-loop-repractice-prestart-chromium-mobile-2026-08-07.png`
데스크톱에서는 홈 추천, 3열 활성 회기, 리뷰 처방과 실행 CTA, 재연습 브리핑이 잘림 없이 읽힌다.
모바일에서는 홈 CTA, 처방의 방식·장면·기준, 재연습 출처가 단일 열로 유지되고 페이지 가로 overflow는 없다.
활성 회기는 390×844와 320×568을 각각 렌더해 아바타/내담자 문구 겹침 0, 중복 상태 배지 숨김,
최신 내담자 발화 완전 노출, 축어록 스크롤·텍스트 입력창의 카드 내부 포함을 수치로 고정했다. 320×568은
실시간 대화를 우선해 시작 전 확인한 호소·이론 요약만 접고 핵심 진행·내담자·마이크 상태는 유지한다.
후속 B1 시각 폴리시였던 리뷰 1~5 척도는 360px 이하에서 의미 순서를 유지한 3+2 배열로 전환했다.
320×568 실측에서 다섯 선택지가 모두 44px 이상이고 척도 내부와 페이지 가로 overflow가 0임을 확인했으며,
`alliance-pulse.spec.ts` desktop/mobile 전체 **8/8 passed**와 척도 고정 캡처를 직접 확인했다.
기존 `session-layout.spec.ts` 모바일 레이아웃 2개 focused 재검증은 화면 경계 단언에 도달하기 전,
공통 pre Alliance 체크포인트 라디오가 React 재렌더로 교체되며 Playwright `.check()`가 안정화되지 않아
각 30초 타임아웃됐다. 이 실패를 레이아웃 통과로 세지 않았고, G1 소유 체크포인트 안정성 문제와 이
문서의 route-fixture 시각 게이트를 분리한다.
## 남은 증거 한계
- 실제 사용자 로그인 + source API + dev DB를 한 브라우저에서 관통한 E2E는 아니다.
- 실제 provider 응답, 물리 마이크, 배포·공개 URL 증거가 아니다.
- route fixture의 처방은 `unassessed` 상태이며 mastery, unseen transfer, 임상 효과를 주장하지 않는다.
- 실 DB production caller 증거와 이 UI 증거는 서버 생산 경계와 화면 소비 경계를 각각 증명한다.
둘을 잇는 인증된 DB-backed 브라우저 폐루프는 별도 게이트다.