vignette/docs/qa/production-computer-use-128-2026-09-09.md
Yun Chan 1306c524c1
Some checks failed
API contract / OpenAPI type drift (push) Failing after 4m46s
회기 집계와 기록 복귀 및 감독 근거 링크 수정
2026-09-09 14:41:54 +09:00

1909 lines
93 KiB
Markdown
Raw Permalink 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.

# 실배포 Computer Use 사용자 E2E 128 실행 카탈로그
- 대상: `https://vignette.chanpaca.net` 실제 배포본과 실제 백엔드
- 관찰 asset: `/assets/index-p7x09Xs2.js`; commit SHA는 확인되지 않아 `null`이다.
- 방식: CUA 실제 브라우저. mock, `page.route`, localStorage 인증 조작, API 직접 write는 금지한다.
- 실행 원장: `outputs/production-cu-2026-09-09/ledger.json`이며 이 카탈로그는 실행 원장을 수정하지 않는다.
- baseline: 128개 모두 `NOT_RUN`, `evidence=[]`. 사전조건 불충족은 실행 시도에서만 `BLOCKED`이며 baseline을 바꾸지 않는다.
- 현재 허용: 로그인한 관리자 계정에서 비식별 검증 회기 2개, 가상 대화, 리뷰·워크시트 저장. 실제 사용자 데이터 수정, 운영 엔진 변경, 자료 공개, 승인 제출, 삭제는 실행하지 않는다.
- 역할 경계: learner_test·teacher_test 검증은 해당 역할 실제 세션으로 한다. 관리자 계정 또는 공간 전환은 접근거부 PASS의 대체가 아니다.
- source에서 확인되지 않은 기능은 `기능확인필요`로 두며 실제 UI가 확인되기 전 PASS로 처리하지 않는다.
## 집계
- 전체: 128
- actor: admin_test 19, authenticated_role 3, learner_test 80, teacher_test 19, unauthenticated 7
- side effect: auth_session 4, none 106, test_data_mutation 14, test_data_mutation_requires_owner_approval 4
## A · 인증
### A01 · 루트 비로그인 진입
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. CUA의 새 비로그인 브라우저 프로필에서 `https://vignette.chanpaca.net/`를 연다.
2. 주소가 `/login`으로 바뀔 때까지 기다린다.
3. `로그인` 제목과 `Google 계정으로 로그인` 버튼을 확인한다.
- 기대결과: 로그인 화면/Google CTA
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; 계정 데이터 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A02 · 학습홈 비로그인 직접주소
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. 비로그인 새 프로필에서 `https://vignette.chanpaca.net/learn`를 연다.
2. `/login`으로 이동한 뒤 로그인 패널의 `Google 계정으로 로그인` 버튼을 확인한다.
3. 학습 대시보드·회기 기록·내담자 목록이 보이지 않는지 확인한다.
- 기대결과: 로그인으로 안전복귀
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; 계정 데이터 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A03 · 실제 존재 학습회기 deep link 비로그인
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필; 실제 존재하는 테스트 회기 ID
- 단계:
1. 비로그인 새 프로필에서 실제 테스트 회기 ID를 넣은 `/learn/session/{테스트회기ID}`를 연다.
2. `/login`으로 이동한 뒤 `Google 계정으로 로그인` 버튼을 확인한다.
3. `실시간 상담 축어록`, `학습자 발화 입력`, 회기 내용이 로그인 전 화면에 없는지 확인한다.
- 기대결과: 내용 미노출 로그인
- side effect: `none`
- 필요 데이터: 실제 존재하는 테스트 회기 ID(비식별); 비로그인 새 브라우저 프로필
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A04 · 교수자콘솔 비로그인
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. 비로그인 새 프로필에서 `https://vignette.chanpaca.net/teach`를 연다.
2. `/login`으로 이동한 뒤 로그인 패널을 확인한다.
3. `교수자 검토 요약`, `학습자 검색`, 학습자 행이 로그인 전 화면에 없는지 확인한다.
- 기대결과: 학생정보 미노출 로그인
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; 계정 데이터 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A05 · 관리자 비로그인
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. 비로그인 새 프로필에서 `https://vignette.chanpaca.net/admin`를 연다.
2. `/login`으로 이동한 뒤 로그인 패널을 확인한다.
3. 관리자 사이드바의 `운영 홈`, `AI 운영`, `사용자`, `티켓`이 로그인 전 화면에 없는지 확인한다.
- 기대결과: 운영정보 미노출 로그인
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; 계정 데이터 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A06 · 로그인 키보드만 OAuth 진입
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. 비로그인 새 프로필에서 `/login`을 연다.
2. Tab으로 `Google 계정으로 로그인` 버튼에 가시 포커스를 이동한다.
3. Enter를 눌러 `accounts.google.com``/v3/signin/accountchooser` 인증 화면을 연다.
4. 계정 선택·제출 전에 중지하고 host와 pathname, `계정을 선택하세요`만 증거로 남긴다.
- 기대결과: 포커스와 Google 인증화면 정상(계정선택 제출 전 중지 가능)
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; Google 계정 선택·제출 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A07 · 일반Google 테스트계정 로그인
- actor: `learner_test`
- 사전조건: 해당 역할로 인증된 테스트 계정
- 단계:
1. `/login`에서 `Google 계정으로 로그인`을 누른다.
2. 소유자가 일반 Google 테스트 계정의 자격증명을 직접 입력하고 인증을 완료한다.
3. 역할 홈(`/learn`, `/teach`, `/admin` 중 해당 경로)에서 사용자 이름과 역할 공간을 확인한다.
4. `승인된 이메일 도메인 또는 관리자 등록 계정만` 차단 문구가 표시되지 않는지 확인한다.
- 기대결과: 허용도메인차단없이 자기계정 진입
- side effect: `auth_session`
- 필요 데이터: 소유자가 직접 입력하는 일반 Google 테스트 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A08 · OAuth 취소후 재시도
- actor: `unauthenticated`
- 사전조건: 비로그인 새 브라우저 프로필
- 단계:
1. 비로그인 상태에서 `/login``Google 계정으로 로그인` 버튼을 누른다.
2. Google 계정 선택 화면에서 제출하지 않고 브라우저 뒤로가기로 `/login`에 돌아온다.
3. 같은 `Google 계정으로 로그인` 버튼을 다시 활성화한다.
4. Google 인증 선택 화면이 다시 열리는지 확인한다.
- 기대결과: 로그인화면 복귀 후 재진입 가능
- side effect: `none`
- 필요 데이터: 비로그인 브라우저 상태; Google 계정 선택·제출 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A09 · 로그인된 사용자의 새탭 진입
- actor: `authenticated_role`
- 사전조건: 비로그인 또는 해당 역할 인증 상태의 브라우저; 실제 사용자 데이터는 읽지 않음
- 단계:
1. 인증된 테스트 계정이 있는 브라우저에서 새 탭을 연다.
2. 새 탭 주소창에 `https://vignette.chanpaca.net/`를 입력한다.
3. 현재 계정의 역할에 맞는 `/learn`, `/teach`, 또는 `/admin` 경로와 역할용 사이드바를 확인한다.
- 기대결과: 역할에 맞는 자기 화면
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A10 · 인증상태 새로고침
- actor: `authenticated_role`
- 사전조건: 해당 역할로 인증된 테스트 계정
- 단계:
1. 인증된 테스트 계정으로 역할 홈을 연다.
2. 브라우저 새로고침을 한 번 실행한다.
3. `/login`으로 반복 이동하지 않고 같은 역할 홈과 사용자 표시가 다시 나타나는지 확인한다.
- 기대결과: 로그아웃루프없이 복원
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A11 · 잘못된 앱주소 복귀
- actor: `authenticated_role`
- 사전조건: 기능확인필요
- 단계:
1. 인증 상태에 맞는 새 탭에서 `/e2e-not-found-20260909`를 연다.
2. 라우터가 안전한 루트로 이동하는 동안 기다린다.
3. 비로그인이면 `/login``Google 계정으로 로그인`, 로그인 상태면 역할 홈을 확인해 앱 탐색을 재개한다.
- 기대결과: 404/안전한홈 이동으로 사용재개
- side effect: `none`
- 필요 데이터: 잘못된 경로 문자열; 계정 데이터 불필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### A12 · 로그아웃후 뒤로가기
- actor: `learner_test`
- 사전조건: 해당 역할로 인증된 테스트 계정
- 단계:
1. 소유자가 허용한 폐기 가능 학습자 테스트 계정으로 `/learn`을 연다.
2. 톱바의 `aria-label=로그아웃` 버튼을 누르고 `/login` 이동을 확인한다.
3. 브라우저 뒤로가기를 한 번 실행한다.
4. `실시간 상담 축어록`, `회기 기록`, `연습 페르소나` 같은 보호 내용이 다시 표시되지 않는지 확인한다.
- 기대결과: 보호된 내용 재노출없음(테스트계정만)
- side effect: `auth_session`
- 필요 데이터: 소유자가 허용한 폐기 가능 학습자 테스트 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## C · 사례 선택
### C01 · 학습홈에서 연습으로 이동
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/learn`을 연다.
2. 사이드바의 `학습` 링크를 선택한다.
3. 주소가 `/learn/practice`인지와 `연습할 내담자를 선택합니다.` 제목을 확인한다.
4. `연습 페르소나` listbox에 실제 서버에서 받은 option 카드가 표시되는지 확인한다.
- 기대결과: 실서버 사례목록 표시
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C02 · 제공 사례 선택
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. `/learn/practice``연습 페르소나` listbox에서 사용 가능한 option 카드 하나를 선택한다.
2. 선택한 카드의 `aria-selected=true`와 체크 표시를 확인한다.
3. 오른쪽 미리보기의 코드·이름이 선택 카드와 같은지 확인한다.
4. `주호소` 아래 요약이 선택 카드의 `presenting_summary`와 일치하는지 확인한다.
- 기대결과: 선택명/미리보기 일치
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C03 · 사례 상세 주호소 확인
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. `연습 페르소나`에서 사용 가능한 테스트 카드를 선택한다.
2. 미리보기의 `주호소` 텍스트를 기록한다.
3. 같은 미리보기에서 `난도`, `접근`, `음성` 값을 별도로 확인한다.
4. 주호소 요약이 난도·접근 값과 섞여 한 필드로 표시되지 않는지 확인한다.
- 기대결과: 해당사례 주호소로 표면화조건과 혼동없음
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C04 · 다른사례 전환
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 첫 번째 사용 가능한 페르소나 option을 선택하고 미리보기 코드·이름·`주호소`를 기록한다.
2. 다른 코드의 사용 가능한 option을 선택한다.
3. 두 번째 카드만 `aria-selected=true`인지 확인한다.
4. 미리보기 코드·이름·`주호소``연습 기록`의 코드가 두 번째 선택과 일치하고 첫 번째 값이 남지 않는지 확인한다.
- 기대결과: 이전사례정보잔류없음
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C05 · 사례별 연습기록 보기
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 테스트 이력이 있는 페르소나 option을 선택한다.
2. `연습 기록` 영역의 `기존 회기` 코드와 회기 수를 확인한다.
3.`회기 기록 목록` 카드의 페르소나 코드가 선택한 카드 코드와 같은지 확인한다.
4. 다른 페르소나를 선택한 뒤 해당 코드의 카드·회기 수로 바뀌는지 확인한다.
- 기대결과: 선택사례 기록만
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C06 · 첫연습 사례 안내
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 기록 0건인 활성 테스트 페르소나
- 단계:
1. 기록이 없는 테스트 페르소나 option을 선택한다.
2. `기존 회기` 수가 0인지와 빈 상태의 `첫 회기를 마치면 실제 저장 기록이 이곳에 쌓입니다.` 안내를 확인한다.
3. 회기 방식의 `완전히 새로 시작`이 선택 가능한지 확인한다.
4. 테스트 회기 생성 권한이 없으면 `완전히 새로 시작`을 누르지 않고 여기서 멈춘다.
- 기대결과: 기록없는사례 첫회기흐름
- side effect: `none`
- 필요 데이터: 기록 0건인 활성 테스트 페르소나
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C07 · 이력있는사례 이어가기 찾기
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 종료 또는 진행 중 이력이 있는 테스트 페르소나 option을 선택한다.
2. `회기 기록 목록`에서 진행 중 카드의 `이어하기`, 종료 카드의 `다음 회기 이어가기`, 리뷰 가능 카드의 `리뷰` 또는 `기록` 조작을 구분해 확인한다.
3. `회기 연속성` 영역이 표시되면 `이어서 진행` 라디오와 `이어서 진행할 사례` 선택 상자의 사용 가능 상태를 확인한다.
4. 새 회기를 만들지 않고 기존 회기와 다음 회기 조작이 구분되는지만 기록한다.
- 기대결과: 기존회기/새회기 구분
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C08 · 사용불가사례 선택시도
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 사용 불가 상태의 사전등록 테스트 페르소나
- 단계:
1. 사용 불가 상태의 사전등록 테스트 페르소나가 목록에 있는지 확인한다.
2. 해당 option의 `aria-disabled=true`, 비활성화 상태, `사용 불가` 배지를 확인한다.
3. 비활성 카드에는 클릭으로 선택 상태가 생기지 않는지 확인한다.
4. 미리보기의 `사용 가능한 내담자가 없습니다.` 또는 카탈로그 차단 안내와 시작 버튼 비활성 조건을 확인한다.
- 기대결과: 시작차단과 이유
- side effect: `none`
- 필요 데이터: 사용 불가 상태의 사전등록 테스트 페르소나
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C09 · 존재하지않는 사례 직접주소
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/learn/session/존재하지않는사례코드`를 연다.
2. 화면이 다른 실제 페르소나의 회기 준비·축어록으로 바뀌지 않는지 확인한다.
3. 표시되는 오류·안전 복귀·로그인 화면 중 실제 결과의 URL과 문구를 기록한다.
- 기대결과: 다른사례로 몰래시작안함
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C10 · 추천사례에서 시작준비
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/learn`을 연다.
2. `다음 연습 추천` 패널의 권장 문구와 `연습 시작하기` 또는 `리뷰 확인하기` 버튼을 확인한다.
3. `연습 시작하기`가 있을 때 누르고 `/learn/practice`로 이동한다.
4. 이동한 미리보기 코드·이름이 추천에서 가리킨 대상과 같은지 확인하고 회기 생성 버튼은 누르지 않는다.
- 기대결과: 추천대상과 준비대상일치
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C11 · 사례선택 키보드조작
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. `/learn/practice`에서 Tab으로 `연습 페르소나`의 option 카드에 포커스를 이동한다.
2. Enter 또는 Space로 사용 가능한 option을 선택한다.
3. 선택 카드의 `aria-selected=true`, 미리보기 변경, `완전히 새로 시작` 또는 `진행 중인 회기 이어가기` 버튼의 사용 가능 상태를 확인한다.
- 기대결과: 포커스/선택/준비가능
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C12 · 모바일 사례탐색
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 브라우저 폭을 390px variant로 설정하고 인증된 학습자 테스트 계정으로 `/learn/practice`를 연다.
2. `연습 페르소나`에서 사용 가능한 option을 선택한다.
3. 미리보기의 `주호소`, `난도`, `접근`, 회기 방식, 시작 버튼까지 스크롤해 접근한다.
4. 가로 스크롤 없이 모든 조작과 텍스트가 보이는지 확인하고 시작 버튼은 누르지 않는다.
- 기대결과: 선택/상세/준비 끝까지 사용가능
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C13 · 상세닫고 목록복귀
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 기능확인필요
- 단계:
1. `/learn/practice`에서 사용 가능한 option을 선택해 오른쪽 미리보기를 연다.
2. 소스에는 별도 상세 닫기 조작이 확인되지 않았으므로, 실제 배포 화면에 닫기 조작이 나타날 때만 그 정확한 라벨을 기록한다.
3. 닫기 조작이 있으면 실행 뒤 `연습 페르소나` listbox와 기존 `aria-selected` 선택이 유지되는지 확인한다.
4. 닫기 조작이 없으면 `기능확인필요`로 기록하고 존재하지 않는 버튼을 추정해 누르지 않는다.
- 기대결과: 선택맥락유지
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C14 · 시작전 이론모드 선택
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 소유자 허용 뒤 테스트 전용 계정·페르소나
- 단계:
1. 소유자가 허용한 테스트 전용 계정·페르소나를 선택한다.
2. 회기 방식과 `완전히 새로 시작`을 확인한 뒤 테스트 회기 생성이 허용된 경우에만 시작한다.
3. 회기 시작 전 준비 화면의 `이론모드 선택` fieldset에서 원하는 이론 버튼을 선택한다.
4. 선택 상태가 준비 화면에 반영되는지 확인하고 실제 학습자 발화는 보내지 않는다.
- 기대결과: 준비화면에선택반영
- side effect: `test_data_mutation_requires_owner_approval`
- 필요 데이터: 소유자 허용 뒤 테스트 전용 계정·페르소나
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C15 · 새등록 테스트페르소나 선택
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 사전등록된 새 테스트 페르소나
- 단계:
1. 사전등록된 새 테스트 페르소나의 code를 가진 option을 `연습 페르소나`에서 선택한다.
2. 미리보기 코드·이름·`주호소`, `난도`, `접근`, `음성`을 확인한다.
3. `완전히 새로 시작` 버튼이 사용 가능한지 확인한다.
4. 회기 생성 허용이 없으면 버튼을 누르지 않고 내담자 정보와 준비 진입 조건만 기록한다.
- 기대결과: 내담자정보/상담준비 정상
- side effect: `none`
- 필요 데이터: 사전등록된 새 테스트 페르소나
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C16 · 퇴역테스트페르소나 deep link
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 퇴역 상태 테스트 페르소나 ID; 기능확인필요
- 단계:
1. 퇴역 상태의 사전등록 테스트 페르소나 code로 `/learn/session/{퇴역테스트페르소나ID}`를 연다.
2. 다른 활성 페르소나의 회기 준비·축어록이 자동으로 열리지 않는지 확인한다.
3. 화면에 나타난 차단·오류·안전 복귀 문구와 URL을 기록하고 신규 회기 시작 조작을 실행하지 않는다.
- 기대결과: 신규회기 차단
- side effect: `none`
- 필요 데이터: 퇴역 상태 테스트 페르소나 ID
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C17 · 두사례간 이력카운트대조
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 테스트 이력이 있는 첫 번째 페르소나 option을 선택한다.
2. `기존 회기` 수와 `회기 기록 목록` 카드의 code·턴 수를 기록한다.
3. 두 번째 테스트 페르소나 option을 선택하고 같은 값을 기록한다.
4. 각 목록 카드가 현재 선택 code만 가지며 두 대상의 수·카드가 섞이지 않는지 확인한다.
- 기대결과: 각기록 혼합없음
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### C18 · 연습주소 새로고침
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/learn/practice`를 연다.
2. 사용 가능한 option을 선택해 `aria-selected=true`와 미리보기 code를 확인한다.
3. 브라우저 새로고침을 한 번 실행한다.
4. 목록 로딩 뒤 선택 option·미리보기·시작 버튼이 유효한 실제 카탈로그 상태인지 확인한다.
- 기대결과: 사례목록과 선택유효성 정상
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## S · 상담
### S01 · 시작전 안내확인
- actor: `learner_test`
- 사전조건: learner_test로 로그인한 실제 브라우저 세션; 실제 배포본 https://vignette.chanpaca.net; 시작하지 않은 테스트 전용 비식별 사례
- 단계:
1. `/learn/practice`에서 테스트 전용 페르소나 option을 선택하고 `완전히 새로 시작`을 누른다.
2. `회기 시작 전 준비``이번 회기 목표 선택`에서 목표 하나를 골라 첫 발화 기준을 확인한다.
3. `회기 시작`을 눌러 실제 회기 작업면을 연다.
4. `첫 발화 전에 내 기준을 잠급니다`에서 `목표`, `과업`, `유대` 각 fieldset의 radio를 하나씩 선택한다.
5. `기준 잠그고 첫 발화 준비`을 누른다.
6. `학습자 발화 입력`이 열리고 첫 발화 전 기준이 잠겼다는 상태를 확인한다.
- 기대결과: 대화전 준비상태명확
- side effect: `none`
- 필요 데이터: 시작 전 상태의 테스트 전용 비식별 사례
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S02 · 테스트회기1개 시작
- actor: `learner_test`
- 사전조건: learner_test로 로그인한 실제 브라우저 세션; 실제 배포본; 진행 중 회기가 없는 테스트 전용 비식별 사례
- 단계:
1. `/learn/practice`에서 비식별 테스트 페르소나를 선택하고 `완전히 새로 시작`을 누른다.
2. `회기 시작 전 준비``이번 회기 목표 선택`에서 목표 하나를 고른다.
3. `회기 시작`을 눌러 새 테스트 회기를 만든다.
4. `첫 발화 전에 내 기준을 잠급니다`에서 `목표`, `과업`, `유대`의 radio를 각각 하나씩 선택한다.
5. `기준 잠그고 첫 발화 준비`을 눌러 회기 전 판단을 잠근다.
6. 표시된 페르소나 코드와 회기 URL의 식별값, `학습자 발화 입력`이 같은 새 회기임을 확인한다.
- 기대결과: 사례/회기 식별일치
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 미사용 테스트 계정과 비식별 사례
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S03 · 무입력전송
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 활성 테스트 회기
- 단계:
1. /learn/session/{테스트회기ID}에서 ‘학습자 발화 입력’의 현재 축어록 턴 수를 기록한다.
2. 입력란을 비운 채 Enter를 누른다.
3. 입력란과 ‘실시간 상담 축어록’을 다시 확인한다.
- 기대결과: 서버턴생성안함
- side effect: `none`
- 필요 데이터: 활성 테스트 회기와 전송 전 턴 수
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S04 · 공백만전송
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 활성 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 공백만 입력하고 현재 턴 수를 기록한다.
2. Enter를 누른다.
3. 공백이 새 학습자 발화나 내담자 응답으로 추가되지 않았는지 확인한다.
- 기대결과: 동일차단
- side effect: `none`
- 필요 데이터: 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S05 · 한국어 첫발화전송
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 새 테스트 전용 비식별 회기
- 단계:
1. ‘학습자 발화 입력’에 ‘실습용 가상 사례에서 오늘의 기분을 한 문장으로 정리해 보고 싶어요.’를 입력한다.
2. Enter를 한 번 누른다.
3. 축어록에 학습자 발화가 먼저 나타나고 실제 내담자 응답이 뒤따르는지 확인한다.
- 기대결과: 실제내담자응답 수신
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 새 테스트 회기와 비개인정보 한국어 입력
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S06 · 두번째맥락발화
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; S05 뒤 내담자 응답이 완료된 동일 테스트 회기
- 단계:
1. 첫 왕복이 끝난 뒤 ‘학습자 발화 입력’에 ‘방금 말한 감정을 더 천천히 살펴보고 싶어요.’를 입력한다.
2. Enter를 한 번 누른다.
3. 축어록의 새 두 턴이 기존 회기 아래에 이어지고 주소의 회기 ID가 바뀌지 않는지 확인한다.
- 기대결과: 같은회기 이어짐
- side effect: `test_data_mutation`
- 필요 데이터: 비개인정보 두 번째 한국어 입력과 기존 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S07 · ShiftEnter 여러줄작성
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 활성 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 ‘실습용 첫 줄’을 입력한다.
2. Shift+Enter를 누르고 ‘실습용 둘째 줄’을 입력한다.
3. 입력란에 두 줄이 유지되고 축어록에 새 턴이 생기지 않았는지 확인한 뒤 입력을 지운다.
- 기대결과: 전송전 줄바꿈보존
- side effect: `none`
- 필요 데이터: 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S08 · Enter전송
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 활성 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 ‘실습용 가상 문장입니다. 다음 단계를 확인하고 싶어요.’를 입력한다.
2. Enter를 한 번 누른다.
3. 입력란이 비고 축어록에 해당 학습자 발화가 정확히 한 번 나타나는지 확인한다.
4. 내담자 응답 완료 뒤에도 같은 문장이 중복되지 않는지 확인한다.
- 기대결과: 1회전송
- side effect: `test_data_mutation`
- 필요 데이터: 비개인정보 한국어 입력과 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S09 · 빠른중복전송
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 활성 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 ‘실습용 중복 방지 확인 문장입니다.’를 입력한다.
2. Enter를 빠르게 두 번 누른다.
3. 축어록에서 해당 학습자 문장이 한 번만 추가되고 내담자 응답이 한 번만 시작되는지 확인한다.
- 기대결과: 중복학습자턴없음
- side effect: `test_data_mutation`
- 필요 데이터: 비개인정보 한국어 입력과 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S10 · 응답중 다음초안작성
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 자연 발생한 내담자 응답 생성 중인 테스트 회기
- 단계:
1. 내담자 응답이 축어록에 진행 중인 상태인지 확인한다.
2. ‘학습자 발화 입력’에 ‘실습용 다음 초안이며 아직 보내지 않습니다.’를 입력한다.
3. 내담자 응답이 끝난 뒤 입력란에 초안이 남아 있고 축어록에는 새 학습자 턴이 없는지 확인한다.
- 기대결과: 초안보존/실전송대기
- side effect: `none`
- 필요 데이터: 응답 생성 중 상태가 자연 발생한 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S11 · 긴정상길이발화
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 테스트 회기
- 단계:
1. 사전 준비한 비개인정보 한국어 긴 문장(제품이 허용하는 길이)을 ‘학습자 발화 입력’에 붙여 넣는다.
2. Enter를 한 번 누른다.
3. 학습자 발화와 내담자 응답의 줄바꿈·문장 끝이 보이고 가로 스크롤이 생기지 않는지 확인한다.
- 기대결과: 잘림/가로넘침없이수신
- side effect: `test_data_mutation`
- 필요 데이터: 제품 허용 길이 안의 비개인정보 긴 한국어 테스트 문자열
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S12 · 허용길이초과입력
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 운영에 전송하지 않아도 되는 테스트 회기; 제품 문자 한도 근거
- 단계:
1. 현재 Session 소스에는 ‘학습자 발화 입력’의 길이 제한이나 초과 차단 문구가 없음을 확인한다.
2. 운영 LLM 전송 없이 검증할 수 있는 사전 설정 한도 데이터가 있는지 확인한다.
3. 그 데이터가 없으면 긴 문자열을 제출하지 않고 BLOCKED로 기록한다.
- 기대결과: UI차단/명확한제한(실LLM과다전송금지)
- side effect: `none`
- 필요 데이터: 프런트 또는 서버의 확인된 문자 한도와 비전송 검증 환경
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S13 · 한영숫자기호혼합
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 ‘실습용 Mix A/B 42! #확인?’을 입력한다.
2. Enter를 한 번 누른다.
3. 축어록의 학습자 턴에서 한글·영문·숫자·기호가 같은 순서로 보이는지 확인한다.
- 기대결과: 깨짐없이표시
- side effect: `test_data_mutation`
- 필요 데이터: 비개인정보 혼합 문자열과 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S14 · 위로스크롤하며대화읽기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 여러 턴이 있는 테스트 회기
- 단계:
1. ‘실시간 상담 축어록’을 위로 스크롤해 과거 발화를 읽는다.
2. 현재 스크롤 위치와 보이는 과거 발화를 확인한다.
3. 자동으로 맨 아래로 이동하지 않는지 확인한다.
- 기대결과: 자동하단강제이동없음
- side effect: `none`
- 필요 데이터: 여러 턴이 저장된 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S15 · 최신으로복귀
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 위로 스크롤한 여러 턴 테스트 회기
- 단계:
1. 축어록을 위로 스크롤해 ‘최신으로’ 버튼을 표시한다.
2. ‘최신으로’를 클릭한다.
3. 마지막 축어록 턴이 보이고 ‘최신으로’ 버튼이 사라지는지 확인한다.
- 기대결과: 마지막턴으로돌아감
- side effect: `none`
- 필요 데이터: 여러 턴이 저장된 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S16 · 도움말 열고닫기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 활성 테스트 회기
- 단계:
1. ‘학습자 발화 입력’에 전송하지 않을 ‘실습용 초안 보존 확인’ 문장을 입력한다.
2. ? 또는 Ctrl+/를 눌러 ‘키보드 단축키 안내’ 대화상자를 연다.
3. Esc 또는 ‘확인 (Esc)’로 닫는다.
4. 입력란의 초안과 기존 축어록이 그대로인지 확인한다.
- 기대결과: 작성문/대화유지
- side effect: `none`
- 필요 데이터: 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S17 · 일시정지후재개
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 응답 생성 중이 아닌 활성 테스트 회기
- 단계:
1. ‘일시정지’를 클릭한다.
2. ‘학습자 발화 입력’의 안내가 ‘일시정지 중입니다.’이고 입력이 막혔는지 확인한다.
3. ‘이어가기’를 클릭한다.
4. 입력란이 다시 활성화되고 상단 경과 표기가 일관되게 이어지는지 확인한다.
- 기대결과: 입력상태/시간흐름일관
- side effect: `none`
- 필요 데이터: 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S18 · 회기설정열고취소
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 활성 테스트 회기
- 단계:
1. 현재 Session 소스에서 활성 회기 중 ‘회기 설정’ 열기·취소 조작이 제공되는지 확인한다.
2. 확인된 활성 회기 설정 제어가 없으면 임의의 패널을 설정으로 간주하지 않는다.
3. 발화·초안 보존을 검증하지 않고 BLOCKED로 기록한다.
- 기대결과: 발화/초안유지
- side effect: `none`
- 필요 데이터: 활성 회기 설정 제어의 실제 배포 증거
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S19 · 회기 새로고침
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 저장된 여러 턴이 있는 테스트 회기
- 단계:
1. 축어록의 학습자·내담자 턴 수와 마지막 문장을 기록한다.
2. 브라우저 새로고침을 수행한다.
3. 동일 /learn/session/{테스트회기ID}에서 기존 턴과 마지막 문장이 복원되고 중복 턴이 없는지 확인한다.
- 기대결과: 저장된턴복원/중복없음
- side effect: `none`
- 필요 데이터: 저장 완료된 여러 턴 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S20 · 다른화면후이어가기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 저장된 턴이 있는 활성 테스트 회기
- 단계:
1. 상단 ‘기록으로’를 클릭해 /learn/history로 이동한다.
2. 브라우저 뒤로 가기로 원래 /learn/session/{테스트회기ID}로 돌아온다.
3. 상단의 ‘이전 회기 기록을 불러왔습니다. 또는 저장된 축어록을 확인하고 같은 회기 ID인지 대조한다.
- 기대결과: 같은회기복원
- side effect: `none`
- 필요 데이터: 저장된 턴이 있는 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S21 · 정상종료확인
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 종료 가능한 테스트 전용 비식별 회기
- 단계:
1. 활성 회기에서 ‘종료하고 리뷰 보기’를 클릭한다.
2. ‘회기를 종료할까요? 대화상자의 저장·리뷰 이동 안내를 확인한다.
3. 대화상자의 ‘종료하고 리뷰 보기’를 한 번 클릭한다.
4. 종료 상태와 /learn/session/{테스트회기ID}/review 이동을 확인한다.
- 기대결과: 종료저장/리뷰이동
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 종료 대상 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S22 · 종료취소
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 활성 테스트 회기
- 단계:
1. ‘종료하고 리뷰 보기’를 클릭해 ‘회기를 종료할까요? 대화상자를 연다.
2. ‘계속 진행’을 클릭한다.
3. 입력란이 ‘종료된 회기입니다. 상태가 아니고 기존 축어록이 유지되는지 확인한다.
- 기대결과: 진행상태유지
- side effect: `none`
- 필요 데이터: 활성 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S23 · 실제응답실패시복구
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 자연 발생한 내담자 응답 실패가 기록된 테스트 전용 회기
- 단계:
1. 자연 발생한 실패 배너와 ‘다시 전송’ 버튼이 보이는 회기인지 확인한다.
2. 실패 전 입력한 비개인정보 발화가 복원됐는지 확인한다.
3. 자연 실패 데이터가 없으면 장애를 유발하지 않고 BLOCKED로 기록한다.
- 기대결과: 초안복원/재전송/부분턴오염없음(실패미관찰이면BLOCKED,고의운영장애금지)
- side effect: `none`
- 필요 데이터: 자연 발생 응답 실패와 비개인정보 발화가 남은 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### S24 · 발화없이종료한별도테스트회기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 발화가 없는 별도 테스트 전용 회기
- 단계:
1. 축어록에 학습자·내담자 발화가 없는 새 테스트 회기인지 확인한다.
2. ‘종료하고 리뷰 보기’를 열고 대화상자의 같은 버튼으로 종료를 확정한다.
3. 리뷰에서 ‘축어록 없음’과 종료 회기 ID를 확인한다.
4. 테스트 계정의 완료 수와 성취 배지가 늘지 않았는지 확인한다.
- 기대결과: 완료수와성취배지증가없음(추가생성필요)
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 발화 없는 별도 테스트 회기와 종료 전 계정 상태
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## R · 리뷰
### R01 · 종료리뷰열기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 종료된 테스트 전용 회기
- 단계:
1. /learn/session/{테스트회기ID}/review를 연다.
2. ‘리뷰 생성 상태’와 화면 주소의 회기 ID를 확인한다.
3. 표시된 사례 정보가 종료 전 회기와 같은지 확인한다.
- 기대결과: 해당사례/회기일치
- side effect: `none`
- 필요 데이터: 종료된 테스트 전용 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R02 · 축어록읽기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 학습자·내담자 턴이 저장된 종료 테스트 회기
- 단계:
1. 리뷰의 ‘축어록’ 탭을 클릭한다.
2. ‘전체’를 선택해 저장된 턴의 화자와 순서를 읽는다.
3. ‘내 발화만’을 눌러 학습자 턴만 남는지 확인한 뒤 ‘전체’로 되돌린다.
- 기대결과: 실제보낸턴/응답순서보존
- side effect: `none`
- 필요 데이터: 순서를 알고 있는 저장 완료 테스트 축어록
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R03 · 리뷰새로고침
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 저장된 축어록과 리뷰 데이터가 있는 종료 테스트 회기
- 단계:
1. ‘축어록’ 탭에서 턴 수와 한 개의 비개인정보 문장을 기록한다.
2. 브라우저를 새로고침한다.
3. 동일 리뷰 주소에서 같은 탭을 열어 기록한 턴과 문장이 유지되는지 확인한다.
- 기대결과: 내용지속
- side effect: `none`
- 필요 데이터: 저장 완료된 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R04 · 피드백탭
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 리뷰 생성 상태가 알려진 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭을 클릭한다.
2. ‘리뷰 생성 상태’의 완료·대기·실패 표시를 읽는다.
3. 상태에 맞춰 ‘감정 타임라인 대기’, ‘평가 대기’, 또는 생성된 피드백 카드가 표시되는지 확인한다.
- 기대결과: 완료/대기/실패상태구분
- side effect: `none`
- 필요 데이터: 평가 상태가 확인된 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R05 · 자기예측이유공란제출
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 예측 revision이 없는 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭에서 ‘첫 자기예측 기록’을 찾는다.
2. ‘성공 가능성’과 ‘이 예측에 대한 확신’을 조절하되 ‘그렇게 예상한 이유’는 비워 둔다.
3. ‘첫 예측 기록’ 버튼이 비활성화되어 새 revision이 만들어지지 않는지 확인한다.
- 기대결과: 검증오류/기록생성없음
- side effect: `none`
- 필요 데이터: 예측 revision이 없는 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R06 · 자기예측정상저장
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 예측 revision이 없는 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭에서 ‘성공 가능성’과 ‘이 예측에 대한 확신’을 선택한다.
2. ‘그렇게 예상한 이유’에 ‘비개인정보 실습 판단: 질문 뒤 감정을 요약하는 반응을 유지할 수 있습니다.’를 입력한다.
3. ‘첫 예측 기록’을 한 번 클릭한다.
4. ‘예측 revision을 기록했어. 외부평가 공개 전 잠금을 완료해줘. 상태 메시지를 확인한다.
- 기대결과: 점수/이유1회저장
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 미기록 종료 테스트 회기와 비개인정보 판단 이유
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R07 · 잠그기전수정
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 잠기지 않은 첫 예측이 있는 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭에서 ‘성공 가능성’을 다른 5% 단위 값으로 바꾼다.
2. ‘그렇게 예상한 이유’에 ‘비개인정보 실습 판단: 이전 판단을 더 보수적으로 조정합니다.’를 입력한다.
3. ‘예측 수정 기록’을 한 번 클릭하고 새 revision 상태 메시지를 확인한다.
- 기대결과: 개정반영
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 잠기지 않은 예측과 비개인정보 판단 이유
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R08 · 자기예측명시잠금
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 잠기지 않은 최신 예측 revision이 있는 종료 테스트 회기
- 단계:
1. ‘명시적 잠금’의 ‘잠근 뒤 수정할 수 없음을 확인했어’ 체크박스를 선택한다.
2. 활성화된 ‘이 예측 잠그기’를 한 번 클릭한다.
3. ‘잠근 예측은 수정할 수 없어’와 ‘독립 수행 관찰’ 표시를 확인한다.
4. 잠금 버튼이 다시 쓰기 동작을 만들지 않는지 확인한다.
- 기대결과: 잠금상태/중복잠금없음
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 잠기지 않은 예측 revision
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R09 · 잠금후새로고침
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; R08에서 잠긴 예측이 있는 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭의 잠금 표시를 확인한다.
2. 브라우저를 새로고침한다.
3. 다시 ‘피드백’ 탭을 열어 ‘예측 수정 기록’ 입력 폼이 없고 잠금 상태가 유지되는지 확인한다.
- 기대결과: 수정금지유지
- side effect: `none`
- 필요 데이터: 잠긴 예측이 저장된 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R10 · 외부평가공개순서
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 같은 조건의 잠기지 않은 회기와 잠긴 회기 각 1개
- 단계:
1. 잠기지 않은 회기의 ‘피드백’ 탭에서 ‘아직 공개하지 않음’ 또는 ‘예측을 잠가야 비교 가능’을 확인한다.
2. 잠긴 회기의 같은 카드를 열어 ‘독립 수행 관찰’과 허용된 평가 범위만 표시되는지 확인한다.
3. 두 회기에서 실제 진단·인구집단 주장이 표시되지 않는지 확인한다.
- 기대결과: 잠금전비공개·잠금후허용범위
- side effect: `none`
- 필요 데이터: 잠금 전·후 상태가 분리된 종료 테스트 회기 2개
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R11 · 비식별가짜이름피드백
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; [NAME]만 포함한 비식별 테스트 축어록이 있는 종료 회기
- 단계:
1. ‘축어록’ 탭을 연다.
2. [NAME]이 있던 테스트 문장이 ‘익명 인물은’ 또는 ‘익명 인물이’로 표시되는지 확인한다.
3. [NAME] 토큰이나 실제 이름이 화면에 남지 않는지 확인한다.
- 기대결과: 상담자/내담자역할치환·실명미노출(실제개인정보금지)
- side effect: `none`
- 필요 데이터: 실제 개인정보 없이 [NAME] 토큰만 가진 테스트 축어록
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R12 · 워크시트빈필수제출
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 워크시트 자동 초안이 있는 종료 테스트 회기
- 단계:
1. ‘워크시트’ 탭에서 ‘사례개념화 워크시트’를 연다.
2. 현재 소스의 저장 버튼은 빈 필수값 검증이 아니라 변경 여부만 확인함을 확인한다.
3. 빈 필수 제출용 검증 문구가 없으므로 임의 저장을 하지 않고 BLOCKED로 기록한다.
- 기대결과: 검증안내
- side effect: `none`
- 필요 데이터: 빈 필수값 검증이 실제로 배포된 테스트 환경
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R13 · 테스트워크시트작성저장
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 저장되지 않은 워크시트 자동 초안이 있는 종료 테스트 회기
- 단계:
1. ‘워크시트’ 탭에서 첫 번째 표시된 워크시트 textarea를 찾는다.
2. 해당 aria-label이 나타내는 항목에 ‘비개인정보 실습 메모: 감정을 요약하고 개방형 질문을 이어간다.’를 입력한다.
3. 활성화된 ‘저장’을 한 번 클릭한다.
4. 상태가 ‘저장된 학습자 제출본’ 또는 ‘저장됨’으로 바뀌는지 확인한다.
- 기대결과: 저장성공
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용을 받은 워크시트 자동 초안과 비개인정보 메모
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R14 · 워크시트다시열기
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; R13 저장본이 있는 종료 테스트 회기
- 단계:
1. ‘워크시트’ 탭에서 저장한 비개인정보 메모를 확인한다.
2. ‘축어록’ 탭으로 이동한 뒤 다시 ‘워크시트’ 탭을 연다.
3. 상태가 ‘저장된 학습자 제출본’이고 저장한 문장이 유지되는지 확인한다.
- 기대결과: 내용보존
- side effect: `none`
- 필요 데이터: 저장 완료된 테스트 워크시트
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R15 · 피드백OFF 테스트계정
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; learnerFeedbackEnabled=false로 사전 설정된 종료 테스트 계정·회기
- 단계:
1. ‘피드백’ 탭을 연다.
2. ‘먼저 예측하고 잠그는 내 기록만 보존합니다’ 제목을 확인한다.
3. ‘감정 밸런스 타임라인’, ‘좋았던 순간’, ‘다음 회기 개선점’ 등 파생 피드백 카드가 표시되지 않는지 확인한다.
- 기대결과: 피드백/파생카드차단(사전설정필요)
- side effect: `none`
- 필요 데이터: 피드백 OFF가 확인된 테스트 계정과 종료 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R16 · 피드백ON 테스트계정
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; learnerFeedbackEnabled=true로 사전 설정된 종료 테스트 계정·회기
- 단계:
1. ‘피드백’ 탭을 연다.
2. ‘먼저 예측하고, 잠근 뒤, 근거로 교정하기’ 제목을 확인한다.
3. 평가 데이터가 있으면 해당 카드가, 없으면 ‘평가 대기’ 또는 ‘아직 생성된 내담자 피드백이 없습니다.’가 표시되는지 확인한다.
- 기대결과: 정상표시(사전설정필요)
- side effect: `none`
- 필요 데이터: 피드백 ON이 확인된 테스트 계정과 종료 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R17 · 리뷰에서다음회기준비
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 전이 또는 처방 반환 intent가 있는 종료 테스트 회기
- 단계:
1. ‘피드백’ 탭에서 반환 intent의 ‘같은 전이 과제로 다시 연습’ 또는 ‘같은 처방으로 다시 연습’을 찾는다.
2. 링크의 출처·성공 기준 안내를 확인한다.
3. 해당 링크를 열어 /learn/practice 주소에 원본 intent 검색값이 유지되는지 확인한다.
4. 기존 리뷰 주소와 저장된 축어록을 다시 열어 남아 있는지 확인한다.
- 기대결과: 같은사례로이동·기존기록보존
- side effect: `none`
- 필요 데이터: 검증된 반환 intent가 있는 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R18 · 비교가능2회리뷰
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 같은 비식별 사례의 종료 테스트 회기 2개
- 단계:
1. 첫 번째 /review에서 ‘축어록’과 ‘피드백’의 회기 ID·근거 턴을 기록한다.
2. 두 번째 /review를 열어 같은 항목을 기록한다.
3. 각 화면이 자기 주소의 회기 ID와 축어록만 표시하고 근거가 섞이지 않는지 대조한다.
- 기대결과: 각회기근거구분
- side effect: `none`
- 필요 데이터: 같은 사례에 속한 종료 테스트 회기 2개
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R19 · 모바일리뷰탭/폼
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 390×844 모바일 뷰포트; 예측 입력 가능한 종료 테스트 회기
- 단계:
1. 390×844에서 /learn/session/{테스트회기ID}/review를 연다.
2. ‘축어록’, ‘피드백’, ‘워크시트’ 탭을 차례로 눌러 각각의 패널이 보이는지 확인한다.
3. ‘피드백’ 탭에서 ‘성공 가능성’과 ‘그렇게 예상한 이유’ 입력란을 스크롤해 완전히 조작 가능한지 확인한다.
4. 가로 스크롤이나 화면 밖에 가려진 탭·입력란이 없는지 확인한다.
- 기대결과: 가로넘침/가려진조작없이완료
- side effect: `none`
- 필요 데이터: 모바일 뷰포트와 예측 입력 가능한 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### R20 · 평가실패회기재시도
- actor: `learner_test`
- 사전조건: learner_test 로그인; 실제 배포본; 자연 발생한 session_end 평가 실패가 기록된 테스트 전용 회기
- 단계:
1. ‘리뷰 생성 상태’에 실제 평가 실패와 재시도 제어가 보이는지 확인한다.
2. 실패 원인 안내와 저장된 축어록을 읽는다.
3. 자연 발생 실패 데이터가 없으면 재평가 요청이나 장애 유발을 하지 않고 BLOCKED로 기록한다.
- 기대결과: 상태안내·기록보존·다음회기막힘없음(실제실패데이터필요)
- side effect: `none`
- 필요 데이터: 자연 발생 session_end 평가 실패가 보존된 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## H · 이력·설정
### H01 · 기록목록이동
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/learn/history`를 연다.
2. `회기 기록을 찾고 정리합니다.` 제목과 `회기 기록` 영역을 확인한다.
3. `회기 기록 목록`의 각 카드에 현재 계정의 페르소나 code·상태·단계·턴 수·날짜가 표시되는지 확인한다.
- 기대결과: 실계정자기기록
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H02 · 기록검색
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 검색 가능한 테스트 페르소나 code 또는 상태 문자열
- 단계:
1. `/learn/history``aria-label=기록 검색` 입력에 테스트 페르소나 code 또는 상태 문자열을 입력한다.
2. 목록 상단의 결과 수와 `회기 기록 목록` 카드를 확인한다.
3. 표시된 카드의 code·단계·상태 중 적어도 하나가 입력한 검색어와 일치하는지 확인한다.
- 기대결과: 일치회기만
- side effect: `none`
- 필요 데이터: 검색 가능한 테스트 페르소나 code 또는 상태 문자열
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H03 · 검색결과없음
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. `기록 검색`에 존재하지 않는 임의 문자열을 입력한다.
2. 빈 상태 문구와 결과 수 0을 확인한다.
3. 입력 내용을 모두 지운다.
4. `전체 회기`과 기존 목록이 다시 표시되는지 확인한다.
- 기대결과: 빈상태와검색해제복구
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H04 · 진행중필터
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 진행 중 테스트 회기
- 단계:
1. `/learn/history``기록 상태 필터`에서 `진행 중` 버튼을 누른다.
2. 버튼의 `aria-pressed=true`와 제목 `진행 중`을 확인한다.
3. 각 결과 카드에 `이어하기`가 있고 종료 카드용 `리뷰`·`기록` 조작이 섞이지 않는지 확인한다.
- 기대결과: 이어가기대상만
- side effect: `none`
- 필요 데이터: 진행 중 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H05 · 종료필터
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 종료 테스트 회기; 기능확인필요; 기능확인필요
- 단계:
1. `/learn/history`에서 종료된 테스트 기록을 먼저 찾는다.
2. 소스의 상태 필터에는 `종료` 항목이 확인되지 않고 `전체`, `진행 중`, `리뷰 필요`, `보관됨`만 있으므로 실제 배포에서 `종료` 필터가 있는지 확인한다.
3. `종료` 필터가 있으면 정확한 버튼 라벨·결과 카드 상태를 기록한다.
4. 없으면 기존 필터를 임의로 대체하지 않고 `기능확인필요`로 기록한다.
- 기대결과: 완료대상만
- side effect: `none`
- 필요 데이터: 종료 테스트 회기; 기능확인필요
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H06 · 리뷰필요필터
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 리뷰 준비 상태 테스트 회기
- 단계:
1. `/learn/history``기록 상태 필터`에서 `리뷰 필요` 버튼을 누른다.
2. `aria-pressed=true`와 목록 제목 `리뷰 필요`를 확인한다.
3. 각 결과 카드가 `리뷰` 조작을 제공하고 `리뷰 가능` 상태인지 확인한다.
- 기대결과: 리뷰대상만
- side effect: `none`
- 필요 데이터: 리뷰 준비 상태 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H07 · 검색+상태조합
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. `기록 검색`에 테스트 페르소나 code를 입력한다.
2. `기록 상태 필터`에서 `진행 중` 또는 `리뷰 필요`를 선택한다.
3. 검색어를 유지한 채 결과 카드가 선택한 상태와 code 조건을 모두 만족하는지 확인한다.
- 기대결과: 두조건유지
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H08 · 목록정렬
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 기능확인필요
- 단계:
1. `/learn/history`를 열고 카드의 시작 날짜를 위에서 아래로 기록한다.
2. 소스는 `sessionSortTime` 내림차순 정렬이며 UI 정렬 버튼은 확인되지 않았으므로 실제 배포에 정렬 조작이 있는지 확인한다.
3. 정렬 조작이 있으면 라벨과 전후 날짜 순서를 기록한다.
4. 정렬 조작이 없으면 날짜 내림차순 목록만 관찰하고 `기능확인필요`로 기록한다.
- 기대결과: 날짜기준일관
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H09 · 특정기록열고뒤로
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 검색어 또는 `리뷰 필요` 필터를 적용한 `/learn/history`에서 특정 카드의 `리뷰` 또는 `기록` 버튼을 누른다.
2. 회기 리뷰의 URL에 해당 session ID가 포함되는지 확인한다.
3. 브라우저 뒤로가기로 `/learn/history`에 돌아온다.
4. 검색어·필터·결과 목록 맥락이 복귀 후 유지되는지 확인한다.
- 기대결과: 목록맥락복귀
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H10 · 테스트종료기록보관
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 소유자 허용 뒤 폐기 가능 종료 테스트 회기
- 단계:
1. 소유자가 명시적으로 허용한 폐기 가능 종료 테스트 회기만 `/learn/history`에서 찾는다.
2. 대상 카드의 code·날짜·턴 수를 증거로 기록하고 `보관` 버튼을 확인한다.
3. 허용이 없으면 버튼을 누르지 않고 safety gate와 `NOT_RUN`을 유지한다.
4. 허용이 있으면 `보관`을 누르고 `회기를 보관했습니다.`와 카드의 `복원` 전환을 확인한다.
5. `보관됨` 필터에서 같은 code·날짜·턴 수의 원본 카드가 남아 있는지 확인한다.
- 기대결과: 보관목록이동·원본보존(사용자허용필요)
- side effect: `test_data_mutation_requires_owner_approval`
- 필요 데이터: 소유자 허용 뒤 폐기 가능 종료 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H11 · 보관기록복원
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 소유자 허용 뒤 보관된 폐기 가능 테스트 회기
- 단계:
1. 소유자가 명시적으로 허용한 보관된 폐기 가능 테스트 회기만 `보관됨` 필터에서 찾는다.
2. 대상 카드의 code·날짜·턴 수를 기록하고 `복원` 버튼을 확인한다.
3. 허용이 없으면 버튼을 누르지 않고 safety gate와 `NOT_RUN`을 유지한다.
4. 허용이 있으면 `복원`을 누르고 `보관을 해제했습니다.`를 확인한다.
5. `전체 회기` 또는 원래 상태 필터에서 같은 원본 카드가 다시 보이는지 확인한다.
- 기대결과: 원래목록복귀
- side effect: `test_data_mutation_requires_owner_approval`
- 필요 데이터: 소유자 허용 뒤 보관된 폐기 가능 테스트 회기
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H12 · 설정화면조회
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/settings`를 연다.
2. 설정 레일의 `계정` 버튼을 선택한다.
3. `계정 요약``표시 이름`, `이메일`, `소속` 필드를 확인한다.
4. 이메일 입력이 비활성화된 로그인 계정 정보인지 확인한다.
- 기대결과: 자기계정정보
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H13 · 테스트계정프로필수정후복원
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정; 소유자 허용 뒤 원래 값을 복원할 수 있는 테스트 계정
- 단계:
1. 소유자가 허용한 테스트 계정으로 `/settings``계정` 섹션을 연다.
2. `표시 이름``소속`의 원래 값을 증거로 기록한다.
3. 한 필드만 비식별 테스트 값으로 바꾸고 `저장`을 누른 뒤 `저장됨`을 확인한다.
4. 새로고침 후 같은 테스트 값이 재조회되는지 확인한다.
5. 원래 값을 다시 입력해 `저장`하고 새로고침하여 원복을 확인한다.
- 기대결과: 저장/재조회일관(기존값보존)
- side effect: `test_data_mutation_requires_owner_approval`
- 필요 데이터: 소유자 허용 뒤 원래 값을 복원할 수 있는 테스트 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### H14 · 설정변경취소
- actor: `learner_test`
- 사전조건: 인증된 학습자 테스트 계정
- 단계:
1. 인증된 학습자 테스트 계정으로 `/settings``계정` 섹션을 연다.
2. `표시 이름` 또는 `소속`에 저장하지 않을 임시 값을 입력한다.
3. 사이드 레일의 다른 설정 섹션(예: `테마`)을 선택한 뒤 `계정`으로 돌아온다.
4. 저장하지 않은 임시 값이 영속화되지 않았고 원래 값이 다시 표시되는지 확인한다.
- 기대결과: 기존값보존
- side effect: `none`
- 필요 데이터: 인증된 테스트 계정; 실제 배포 데이터는 읽기 전용으로 관찰
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## T · 교수자
### T01 · 교수자로그인홈
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 계정으로 로그인 완료; 실제 배포본 https://vignette.chanpaca.net; 비식별 테스트 회기만 조회
- 단계:
1. 로그인된 teacher_test 세션에서 /teach 를 연다.
2. 상단 역할 표기가 ‘교수자’이고 제목이 ‘교수 콘솔’인지 확인한다.
3. ‘학생 분석’과 ‘새로고침’ 버튼이 표시되는지 확인한다.
4. 주소가 /teach 이고 관리자 편집 제어가 보이지 않는지 기록한다.
- 기대결과: 허용콘솔
- side effect: `auth_session`
- 필요 데이터: teacher_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T02 · 학습자권한교수주소시도
- actor: `learner_test`
- 사전조건: 인증된 learner_test 역할의 실제 브라우저 세션; admin 역할·admin 공간 전환으로 대체 검증 금지
- 단계:
1. teacher_test 세션에서 /admin/users 주소를 직접 연다.
2. 관리자 사용자 목록이나 ‘가입 승인과 권한 관리’가 표시되지 않는지 확인한다.
3. 권한 오류, 차단 화면 또는 허용된 교수자 경로로의 전환을 확인한다.
4. 주소와 화면의 접근 차단 상태를 기록한다.
- 기대결과: 차단
- side effect: `none`
- 필요 데이터: learner_test 계정; 관리자 계정은 접근거부 PASS를 대체하지 않음
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T03 · 대기목록에서테스트학습자리뷰
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 비식별 test_learner와 종료·review_ready 테스트 회기 1건이 교수자 큐에 존재
- 단계:
1. /teach 에서 test_learner가 포함된 최근 회기 행을 찾는다.
2. 그 행의 ‘상세 리뷰’ 동작을 선택한다.
3. 주소가 /teach/session/{test_session_id}/review 이고 리뷰 헤더의 학습자·세션이 선택 행과 일치하는지 확인한다.
4. 리뷰 생성 상태가 ‘준비됨’인지 확인한다.
- 기대결과: 대상일치
- side effect: `none`
- 필요 데이터: test_learner 표시명, 종료·review_ready 테스트 session_id
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T04 · 종료상태와리뷰상태구분
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 종료된 test_learner 회기 2건(검토 대기 1건, 검토 완료 또는 메모 저장 1건) 존재
- 단계:
1. /teach 에서 두 테스트 회기의 종료 상태와 검토 배지를 확인한다.
2. 검토 대기 행과 검토 완료 또는 메모 저장 행을 각각 연다.
3. 각 상세 리뷰의 세션 종료 표시와 교수자 검토 상태가 행의 배지와 일치하는지 확인한다.
4. 종료 여부와 검토 여부가 하나의 같은 상태로 합쳐져 표시되지 않는지 기록한다.
- 기대결과: 대기/완료명확
- side effect: `none`
- 필요 데이터: 상태가 다른 비식별 종료 테스트 회기 2건
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T05 · 학습자검색
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; test_learner의 표시명 또는 비식별 ID가 학생 분석 목록에 존재
- 단계:
1. /teach/analysis 에서 ‘학습자 검색’ 입력칸을 찾는다.
2. test_learner의 고유 검색 문자열을 입력한다.
3. 검색 가능한 학습자 추이 테이블에 해당 학습자만 남는지 확인한다.
4. 남은 행의 표시명 또는 ID가 입력한 테스트 대상과 일치하는지 확인한다.
- 기대결과: 일치대상
- side effect: `none`
- 필요 데이터: test_learner 표시명 또는 비식별 ID
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T06 · 미일치검색복구
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 학생 분석 목록에 test_learner 존재
- 단계:
1. /teach/analysis 의 ‘학습자 검색’에 존재하지 않는 비식별 문자열을 입력한다.
2. ‘검색 결과 없음’ 빈 상태와 검색어를 줄이라는 안내를 확인한다.
3. 입력값을 모두 지운다.
4. test_learner 행이 다시 표시되고 이전 빈 상태가 사라지는지 확인한다.
- 기대결과: 빈상태/해제정상
- side effect: `none`
- 필요 데이터: 존재하지 않는 비식별 검색 문자열, test_learner
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T07 · 최신활동정렬
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 서로 다른 최근 활동 시각을 가진 비식별 학습자 2명 이상 존재
- 단계:
1. /teach/analysis 의 ‘학습자 정렬’에서 최신 활동 정렬 제어를 선택한다.
2. 목록 첫 두 행의 최근 활동 시각 또는 같은 기준으로 표시된 최신 회기를 확인한다.
3. 첫 행이 둘째 행보다 오래되지 않았는지 확인한다.
4. 정렬 전후 선택한 학습자 검색 조건이 유지되는지 확인한다.
- 기대결과: 목록정렬일관
- side effect: `none`
- 필요 데이터: 최근 활동 시각이 다른 test_learner 2명 이상
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T08 · 회기수정렬
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 완료 회기 수가 다른 비식별 학습자 2명 이상 존재
- 단계:
1. /teach/analysis 의 ‘학습자 정렬’에서 회기 수 정렬 제어를 선택한다.
2. 표의 ‘회기’ 열에서 첫 두 행의 수치를 확인한다.
3. 선택한 정렬 방향과 수치 순서가 일치하는지 확인한다.
4. 행을 새로 열지 않아도 정렬이 화면 값만 바꾸고 데이터를 수정하지 않는지 확인한다.
- 기대결과: 값과순서일치
- side effect: `none`
- 필요 데이터: 완료 회기 수가 다른 test_learner 2명 이상
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T09 · 학습자요약펼침닫힘
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 학생 분석 목록에 비식별 학습자 2명 이상 존재
- 단계:
1. /teach/analysis 에서 첫 test_learner 행의 ‘요약 펼치기’ 버튼을 선택한다.
2. 그 행에만 회기·점수·추이 요약이 열리는지 확인한다.
3. 같은 행의 ‘요약 접기’를 선택한다.
4. 둘째 행의 펼침 상태와 표시 값이 바뀌지 않았는지 확인한다.
- 기대결과: 다른행상태오염없음
- side effect: `none`
- 필요 데이터: test_learner 2명 이상
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T10 · 상세분석진입복귀
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; test_learner가 학생 분석 목록에 존재
- 단계:
1. /teach/analysis 에서 test_learner 행의 ‘상세 보기’를 선택한다.
2. 상세 제목의 학습자 표시명이 선택한 행과 같은지 확인한다.
3. 상단 ‘콘솔로’ 버튼을 선택한다.
4. /teach 로 돌아오고 로그인 역할이 교수자로 유지되는지 확인한다.
- 기대결과: 같은학습자맥락
- side effect: `none`
- 필요 데이터: test_learner
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T11 · 분석탭전환
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 상세 분석에 들어갈 test_learner 존재
- 단계:
1. test_learner의 상세 분석을 연다.
2. ‘학습자 상세 분석 탭’에서 ‘페르소나별 회기’, ‘회기별 추이’, ‘전체 회기’, ‘단계 분포’를 차례로 선택한다.
3. 각 탭에서 선택된 탭만 활성 상태이고 해당 섹션 제목 또는 빈 상태가 보이는지 확인한다.
4. 탭 전환 뒤 학습자 이름과 분석 요약 수치가 동일 대상의 값으로 유지되는지 확인한다.
- 기대결과: 선택에맞는데이터
- side effect: `none`
- 필요 데이터: test_learner
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T12 · 페르소나별기록그룹열기
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; test_learner에 특정 페르소나 완료 회기 1건 이상 존재
- 단계:
1. test_learner 상세의 ‘페르소나별 회기’ 탭을 연다.
2. 대상 페르소나의 ‘회기 펼치기’ 버튼을 선택한다.
3. 펼친 그룹의 회기 수와 대상 session_id 또는 회기 번호가 사전 설정 자료와 일치하는지 확인한다.
4. 다른 페르소나 그룹을 열지 않은 상태에서 대상 그룹만 확장되는지 확인한다.
- 기대결과: 해당사례기록
- side effect: `none`
- 필요 데이터: test_learner, 페르소나 코드, 해당 테스트 session_id
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T13 · 회기타임라인개별리뷰
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; test_learner의 종료·review_ready 테스트 session_id 존재
- 단계:
1. test_learner 상세의 ‘전체 회기’ 탭을 연다.
2. 대상 회기 번호의 ‘상세 리뷰’ 또는 ‘진행 기록’ 버튼을 선택한다.
3. 주소의 session_id와 타임라인에서 선택한 test_session_id가 일치하는지 확인한다.
4. 종료 회기라면 리뷰 화면의 축어록 또는 리뷰 준비 상태가 표시되는지 확인한다.
- 기대결과: 정확한회기
- side effect: `none`
- 필요 데이터: test_learner, 종료·review_ready test_session_id
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T14 · 추이차트부족데이터
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 평가 점수 또는 추이 표본이 부족한 test_learner 존재
- 단계:
1. 표본 부족 test_learner의 상세 분석에서 ‘회기별 추이’를 연다.
2. 차트가 값 없는 항목을 ‘저장된 점수 없음’ 또는 중립 빈 상태로 표시하는지 확인한다.
3. ‘상승’·‘하락’ 같은 근거 없는 추이 단정이 표시되지 않는지 확인한다.
4. 다른 탭의 회기 수와 차트에 표시된 표본 수가 모순되지 않는지 확인한다.
- 기대결과: 무근거성과단정없음
- side effect: `none`
- 필요 데이터: 평가 표본 부족 test_learner
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T15 · 테스트학습자검토메모임시작성취소
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 종료·review_ready test_session_id 존재
- 단계:
1. 대상 /teach/session/{test_session_id}/review 의 교수자 검토 영역을 연다.
2. ‘교수자 검토 메모’에 CUA 임시 메모 - 저장 금지’를 입력한다.
3. ‘메모 저장’을 누르지 않고 ‘전체 회기’ 탭으로 이동한 뒤 같은 리뷰를 다시 연다.
4. 임시 문자열과 저장 시각이 남지 않았는지 확인한다.
- 기대결과: 저장안됨
- side effect: `none`
- 필요 데이터: 비식별 종료 테스트 회기 1건
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T16 · 테스트워크시트검토저장
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 소유자가 허용한 비식별 test_learner의 저장된 워크시트와 종료·review_ready test_session_id 존재; 테스트 뒤 정리 가능한 테스트 자료만 사용
- 단계:
1. 대상 /teach/session/{test_session_id}/review 에서 ‘워크시트 검수’를 연다.
2. ‘워크시트 검수 메모’에 비식별 테스트 문자열을 입력한다.
3. ‘수정요청’을 실제로 선택하고 저장 완료 상태 또는 검수 시각이 표시될 때까지 기다린다.
4. 같은 URL을 새로고침하거나 목록에서 다시 열어 메모·수정요청 상태·검수 시각이 같은 test_session_id에만 남았는지 재조회한다.
5. 다른 테스트 회기의 워크시트 상태가 바뀌지 않았는지 확인한다.
- 기대결과: 해당테스트항목만저장(승인필요)
- side effect: `test_data_mutation`
- 필요 데이터: 소유자 허용 비식별 워크시트 test_session_id, 저장된 학습자 워크시트
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T17 · 안전큐대상열기
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 비식별 test_learner의 사전 설정 안전 알림 테스트 회기 존재
- 단계:
1. /teach 의 ‘위기 알림’ 큐에서 비식별 테스트 항목만 찾는다.
2. 항목의 학습자 라벨·페르소나 코드·위험도·session_id 앞부분이 사전 설정한 테스트 자료와 일치하는지 확인한다.
3. 큐가 원문 축어록이나 실제 연락처를 노출하지 않고 안내 번호·리소스 제목만 표시하는지 확인한다.
4. 알림 상태를 승인·해결로 변경하지 않고 화면을 닫는다.
- 기대결과: 해당테스트위기회기·안내(실제학생정보최소화)
- side effect: `none`
- 필요 데이터: 비식별 안전 알림 test_session_id
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T18 · 감독·연구화면
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. 교수자 사이드바에서 ‘감독·연구’를 선택하거나 /teach/supervision 을 연다.
2. 감독 우선순위와 증거 매니페스트 영역이 표시되는지 확인한다.
3. 관리자 전용 지속 개선 승인 원장이나 사용자 권한 편집 제어가 표시되지 않는지 확인한다.
4. 교수자 역할 표기와 주소가 유지되는지 기록한다.
- 기대결과: 권한내기능표시
- side effect: `none`
- 필요 데이터: teacher_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T19 · 모바일교수자목록검색리뷰
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 390px 폭; test_learner와 종료·review_ready test_session_id 존재
- 단계:
1. 390px 폭에서 /teach/analysis 를 열고 ‘학습자 검색’에 test_learner를 입력한다.
2. 가로 스크롤 없이 대상 행의 ‘상세 보기’를 선택한다.
3. ‘전체 회기’ 탭에서 대상 session_id의 상세 리뷰를 연다.
4. 리뷰 헤더·탭·뒤로가기 동작이 화면 밖으로 잘리지 않는지 확인한다.
- 기대결과: 핵심동선조작가능
- side effect: `none`
- 필요 데이터: test_learner, test_session_id
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### T20 · 교수자홈버튼
- actor: `teacher_test`
- 사전조건: 승인된 teacher_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. /teach/analysis 를 열어 ‘학생 분석’ 화면인지 확인한다.
2. 헤더의 ‘콘솔로’ 버튼을 선택한다.
3. 주소가 정확히 /teach 로 바뀌고 제목이 ‘교수 콘솔’로 바뀌는지 확인한다.
4. 경로가 유지되거나 잘못된 화면으로 이동하면 URL·화면 제목을 불일치 증거로 기록한다.
- 기대결과: 정상/teach복귀(경로불일치후보확인)
- side effect: `none`
- 필요 데이터: teacher_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
## O · 관리자
### O01 · 관리자로그인홈
- actor: `admin_test`
- 사전조건: 승인된 admin_test 계정으로 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. 로그인된 admin_test 세션에서 /admin 을 연다.
2. 역할 표기가 ‘관리자’이고 제목이 ‘현재 서비스 상태’인지 확인한다.
3. ‘새로고침’과 운영 요약이 표시되는지 확인한다.
4. 사용자 변경·운영 설정 저장 버튼은 누르지 않는다.
- 기대결과: 권한내콘솔
- side effect: `auth_session`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O02 · 학습자관리주소
- actor: `learner_test`
- 사전조건: 인증된 learner_test 역할의 실제 브라우저 세션; admin 역할·admin 공간 전환으로 대체 검증 금지
- 단계:
1. admin_test 세션에서 /learn 주소를 직접 연다.
2. 학습자 홈의 학습 시작 제어와 개인 회기 목록이 관리자에게 표시되지 않는지 확인한다.
3. 권한 오류, 차단 화면 또는 허용된 관리자 경로 전환을 확인한다.
4. 주소와 접근 차단 상태를 기록한다.
- 기대결과: 접근차단
- side effect: `none`
- 필요 데이터: learner_test 계정; 관리자 계정은 접근거부 PASS를 대체하지 않음
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O03 · 운영홈서비스상태읽기
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. /admin 의 ‘현재 서비스 상태’에서 상태 문구·환경·엔진 모드·갱신 시각을 읽는다.
2. ‘새로고침’을 한 번 선택하고 완료 뒤 갱신 시각이 표시되는지 확인한다.
3. 운영 요약의 활성 회기·온라인 사용자 수가 숫자 또는 명시적 빈 값으로 표시되는지 확인한다.
4. 상태 값을 변경하거나 진단 조치를 실행하지 않는다.
- 기대결과: 실제상태/갱신시각명확
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O04 · AI운영기간변경
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. /admin/ai 의 ‘계량 기간’에서 현재 선택값을 기록한다.
2. 표시된 다른 기간 버튼을 선택한다.
3. ‘일별 비용 흐름’ 차트의 aria-label과 기간 표시가 선택한 일수로 바뀌는지 확인한다.
4. ‘최근 집계’ 시각과 모델별 사용 원장이 새 기간 기준으로 다시 표시되는지 확인한다.
- 기대결과: 집계기간반영
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O05 · 모델별사용원장읽기
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 선택 기간에 비식별 사용 원장 또는 명시적 빈 상태 존재
- 단계:
1. /admin/ai 에서 AI 사용 핵심 지표’와 모델별 사용 원장 영역을 연다.
2. 모델명, 호출 수, 토큰 또는 비용 단위, 비용 기준 라벨이 함께 표시되는지 확인한다.
3. 미계량 호출이 있으면 복원하지 않고 미계량이라는 설명이 표시되는지 확인한다.
4. 원문 프롬프트·응답·개인 식별 정보가 표에 보이지 않는지 확인한다.
- 기대결과: 모델/계량단위명확
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O06 · AI설정열고취소
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 현재 AI 엔진 설정이 조회 가능
- 단계:
1. /admin/ai 의 AI 운영 설정’에서 현재 공급자·연결 주소·기본 모델·추론 강도를 기록한다.
2. 저장 제어를 누르지 않고 모델 목록 또는 설정 영역만 연다.
3. ‘운영 설정 저장’을 선택하지 않은 채 /admin 으로 이동한다.
4. 다시 /admin/ai 를 열어 기록한 설정 값이 변하지 않았는지 확인한다.
- 기대결과: 운영설정변경없음
- side effect: `none`
- 필요 데이터: admin_test 계정, 현재 표시된 엔진 모드·모델 값
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O07 · 사용자검색
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 비식별 test_learner 계정이 사용자 목록에 존재
- 단계:
1. /admin/users 에서 ‘사용자 목록’ 탭을 선택한다.
2. ‘사용자 검색’에 test_learner의 고유 비식별 검색 문자열을 입력한다.
3. 남은 행의 표시 이름·역할이 사전 설정한 테스트 계정과 일치하는지 확인한다.
4. 행의 저장·승인·역할 선택 제어는 누르지 않는다.
- 기대결과: 대상일치
- side effect: `none`
- 필요 데이터: test_learner 표시명 또는 비식별 이메일 식별자
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O08 · 사용자검색없음
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 사용자 목록 조회 가능
- 단계:
1. /admin/users 의 ‘사용자 목록’ 탭에서 ‘사용자 검색’에 존재하지 않는 문자열을 입력한다.
2. 검색 조건에 맞는 사용자가 없다는 빈 상태가 표시되는지 확인한다.
3. 검색어를 지운다.
4. 목록이 돌아오고 사용자 편집값이 바뀌지 않았는지 확인한다.
- 기대결과: 빈상태/복귀
- side effect: `none`
- 필요 데이터: 존재하지 않는 비식별 검색 문자열
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O09 · 사용자정렬
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 사용자 목록에 비식별 계정 2개 이상 존재
- 단계:
1. /admin/users 의 ‘사용자 목록’에서 정렬 가능한 열 머리글을 선택한다.
2. 첫 두 행의 해당 열 값을 기록한다.
3. 같은 열 머리글을 다시 선택해 정렬 방향을 바꾼다.
4. 방향 표시와 두 행의 값 순서가 일치하고 사용자 편집 제어가 실행되지 않았는지 확인한다.
- 기대결과: 값/순서일관
- side effect: `none`
- 필요 데이터: 비식별 사용자 2개 이상
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O10 · 테스트사용자상세
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 비식별 test_learner 계정이 사용자 목록에 존재
- 단계:
1. /admin/users 의 ‘사용자 목록’에서 test_learner를 검색한다.
2. 해당 행을 펼쳐 표시 이름, 역할, 승인 상태, ‘학습자 AI 피드백’ 값을 확인한다.
3. 표시된 역할·피드백 상태가 사전 설정된 테스트 값과 일치하는지 확인한다.
4. select·switch·저장 버튼을 조작하지 않고 행을 다시 접는다.
- 기대결과: 역할/피드백상태확인
- side effect: `none`
- 필요 데이터: test_learner 계정의 사전 설정 역할·AI 피드백 값
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O11 · 권한정책화면
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. /admin/access 에서 ‘역할’ 탭을 연다.
2. 관리자·교수자·학습자 정책 카드와 권한 수가 표시되는지 확인한다.
3. ‘권한 매트릭스’ 탭을 선택해 리소스별 세 역할 열이 표시되는지 확인한다.
4. 화면이 정책 표시 전용이며 역할·그룹 저장 API가 분리되지 않았다는 안내를 확인한다.
- 기대결과: 접근정책표시
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O12 · 프로토콜메뉴접근
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 프로토콜을 생성하지 않는 읽기 전용 확인
- 단계:
1. /admin/access 에서 aria-label ‘접근 권한 탭’의 ‘상담 프로토콜’을 선택한다.
2. ‘상담 프로토콜 초안 등록’ 제목과 ‘등록 프로토콜’ 목록이 함께 표시되는지 확인한다.
3. ‘프로토콜 제목’, ‘프로토콜 출처’, ‘프로토콜 버전’, ‘프로토콜 라이선스’, ‘프로토콜 원문’ 입력 제어를 확인한다.
4. 초안 등록·활성화·퇴역 버튼은 누르지 않는다.
- 기대결과: 목록/신규폼존재
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O13 · 프로토콜검색상태필터
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 제목 또는 상태가 알려진 비식별 테스트 프로토콜 존재
- 단계:
1. /admin/access 의 ‘상담 프로토콜’ 탭에서 ‘프로토콜 검색’에 테스트 제목 조각을 입력한다.
2. ‘프로토콜 상태 필터’를 사전 설정 상태로 선택한다.
3. 남은 카드의 제목과 상태 배지가 둘 다 기대값과 일치하는지 확인한다.
4. 검색어와 필터를 원래 값으로 되돌리고 목록이 복구되는지 확인한다.
- 기대결과: 일치항목
- side effect: `none`
- 필요 데이터: 비식별 테스트 프로토콜 제목 조각과 사전 설정 상태
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O14 · 프로토콜빈필수초안등록
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 프로토콜 목록의 시작 개수 또는 대상 제목 부재를 기록
- 단계:
1. /admin/access 의 ‘상담 프로토콜’ 탭에서 필수 입력을 모두 빈 값으로 둔다.
2. ‘초안 등록’을 한 번 선택한다.
3. ‘제목, 출처, 원문을 모두 입력해야 합니다. 오류가 표시되는지 확인한다.
4. 등록 프로토콜 목록에 새 카드가 생기지 않았는지 확인한다.
- 기대결과: 오류안내·생성없음
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O15 · 프로토콜초안작성취소
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 프로토콜 목록과 기존 검색 결과를 기록
- 단계:
1. ‘상담 프로토콜 초안 등록’에 비식별 임시 제목·출처·원문을 입력한다.
2. ‘초안 등록’을 누르지 않고 ‘역할’ 탭으로 이동한다.
3. 다시 ‘상담 프로토콜’ 탭을 열어 임시 입력이 새 카드로 생성되지 않았는지 확인한다.
4. 기존 프로토콜 카드 수와 검색 결과가 시작 기록과 같은지 확인한다.
- 기대결과: 기존자료영향없음
- side effect: `none`
- 필요 데이터: 비식별 임시 제목·출처·원문 문자열
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O16 · 티켓복합필터
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 비식별 테스트 티켓이 사전 설정된 상태·카테고리·우선순위로 존재
- 단계:
1. /admin/tickets 에서 ‘티켓 검색’에 테스트 제목 조각을 입력한다.
2. ‘상태 필터’, ‘카테고리 필터’, ‘우선순위 필터’를 사전 설정값으로 선택한다.
3. 미해결 운영 티켓 큐에 남은 카드가 목표 티켓과 일치하는지 확인한다.
4. 티켓 상태 변경·해결 노트 저장 제어는 누르지 않는다.
- 기대결과: 일치티켓목록
- side effect: `none`
- 필요 데이터: 비식별 테스트 티켓의 제목 조각·상태·카테고리·우선순위
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O17 · 티켓상세열고복귀
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; O16의 복합 필터로 남는 비식별 테스트 티켓 존재
- 단계:
1. /admin/tickets 에서 O16과 같은 검색·필터를 적용한다.
2. 남은 테스트 티켓의 상세 열기 제어를 선택한다.
3. 제목·상태·카테고리가 선택한 카드와 일치하는지 확인한다.
4. 뒤로 또는 목록 복귀 후 검색어와 필터, 남은 카드가 유지되는지 확인한다.
- 기대결과: 필터맥락유지
- side effect: `none`
- 필요 데이터: 비식별 테스트 티켓
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O18 · 개선원장상태조회
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 실제 배포본 https://vignette.chanpaca.net
- 단계:
1. /admin/continuous-improvement 를 열고 ‘승격보다 근거를 먼저 본다’ 헤더를 확인한다.
2. 운영 경계, 콘텐츠 검증 단계, 게이트 필수 증거, 수명주기 원장을 차례로 확인한다.
3. 후보의 증거 상태와 사람 승인 이후 효과가 다른 영역으로 분리되어 있는지 확인한다.
4. ‘원장 새로고침’ 외의 승인·보류·반려 제어는 누르지 않는다.
- 기대결과: 후보/증거/실행결정구분
- side effect: `none`
- 필요 데이터: admin_test 계정
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O19 · 증거부족후보승인시도
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 필수 증거가 부족한 비식별 후보가 지속 개선 원장에 존재
- 단계:
1. /admin/continuous-improvement 에서 증거 부족 후보의 ‘게이트 필수 증거’ 상태를 확인한다.
2. ‘필수 증거 4종 미완료로 승인 차단’ 또는 해당 차단 사유를 확인한다.
3. 그 후보의 승인 버튼이 disabled 상태인지 접근성 상태와 화면으로 확인한다.
4. 승인·보류·반려 선택이나 제출 버튼은 어떤 것도 누르지 않고 차단 관찰만 기록한다.
- 기대결과: 승인차단(실제승인제출금지)
- side effect: `none`
- 필요 데이터: 증거 부족 비식별 후보
- baseline 상태: `NOT_RUN`
- evidence: `[]`
### O20 · 모바일관리자검색상세
- actor: `admin_test`
- 사전조건: 승인된 admin_test 로그인 완료; 390px 폭; 비식별 test_learner 계정 존재
- 단계:
1. 390px 폭에서 /admin/users 의 ‘사용자 목록’ 탭을 연다.
2. ‘사용자 검색’에 test_learner를 입력한다.
3. 가로 스크롤 없이 대상 행의 상세를 열어 역할·승인 상태·학습자 AI 피드백 상태를 확인한다.
4. 저장·승인·역할 변경 없이 상세를 닫고, 입력·필터·제어가 화면 밖으로 잘리지 않는지 확인한다.
- 기대결과: 가로넘침없이핵심조작
- side effect: `none`
- 필요 데이터: test_learner 표시명 또는 비식별 이메일 식별자
- baseline 상태: `NOT_RUN`
- evidence: `[]`