feat: 운영 안정성과 세션 음성 경험 개선
This commit is contained in:
parent
facc4ad2d9
commit
c788343467
95 changed files with 8431 additions and 1785 deletions
|
|
@ -15,8 +15,8 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타
|
|||
|
||||
| 검증 | 작업 디렉터리 | 명령 | DB | API(8000) | 웹(5173) | 엔진GW(9099) | 브라우저 | 현재 통과 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| 백엔드 단위 테스트 | `apps/api` | `python -m pytest app/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 2026-07-15 전체 실행 400 passed |
|
||||
| 엔진 게이트웨이 테스트 | `apps/api` | `python -m pytest engine_gateway/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 현재 29 pass |
|
||||
| 백엔드 단위 테스트 | `apps/api` | `python -m pytest app/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 2026-07-30 전체 실행 432 passed |
|
||||
| 엔진 게이트웨이 테스트 | `apps/api` | `python -m pytest engine_gateway/ -q` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | 2026-07-30 전체 실행 44 passed |
|
||||
| API 타입 생성 체크 | `apps/web` | `npm run check:api-types` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
|
||||
| 웹 타입체크 | `apps/web` | `npm run typecheck` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
|
||||
| 웹 빌드 | `apps/web` | `npm run build` | 불필요 | 불필요 | 불필요 | 불필요 | 불필요 | pass |
|
||||
|
|
@ -42,15 +42,15 @@ Vignette 저장소의 모든 검증 수단(백엔드 단위 테스트, 웹 타
|
|||
|
||||
```sh
|
||||
# apps/api
|
||||
python -m pytest app/ -q # 앱 단위 테스트: 2026-07-15 전체 실행 400 passed
|
||||
python -m pytest engine_gateway/ -q # 게이트웨이 단위 테스트 현재 29 pass
|
||||
python -m pytest app/ -q # 앱 단위 테스트: 2026-07-30 전체 실행 432 passed
|
||||
python -m pytest engine_gateway/ -q # 게이트웨이 단위 테스트: 2026-07-30 전체 실행 44 passed
|
||||
```
|
||||
|
||||
수집만 빠르게 확인하려면:
|
||||
|
||||
```sh
|
||||
python -m pytest app/ --collect-only -q # 현재: "400 tests collected" (2026-07-15)
|
||||
python -m pytest engine_gateway/ --collect-only -q # 현재: "29 tests collected"
|
||||
python -m pytest app/ --collect-only -q # 현재: "432 tests collected" (2026-07-30)
|
||||
python -m pytest engine_gateway/ --collect-only -q # 현재: "44 tests collected" (2026-07-30)
|
||||
```
|
||||
|
||||
> 참고: 실행 중 `PendingDeprecationWarning: Please use 'import python_multipart'`
|
||||
|
|
@ -80,6 +80,7 @@ python -m pytest engine_gateway/ --collect-only -q # 현재: "29 tests collected
|
|||
| 파일 | 검증 영역 |
|
||||
|---|---|
|
||||
| `engine_gateway/test_gateway_model.py` | 게이트웨이 모델 선택·공유 engine contract·SSE 요청/응답 계약(ENGINE_MODE별) |
|
||||
| `engine_gateway/test_provider_registry.py` | Claude/Anthropic/Codex/Agy capability 정규화, 기본값, CLI 인자, 잘못된 모델·추론 강도 차단 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -131,7 +132,7 @@ python scripts/smoke-resistance-openness-db.py \
|
|||
npm install # 최초 1회 (devDependencies: typescript, vite, @playwright/test 등)
|
||||
npm run check:api-types # FastAPI OpenAPI ↔ src/lib/api.gen.ts 동기화 확인
|
||||
npm run typecheck # tsc -b — 타입 오류 0 확인
|
||||
npm run build # tsc -b && vite build — 프로덕션 번들 생성까지 확인
|
||||
npm run build # cosmetic-filter namespace gate → tsc -b → vite build
|
||||
```
|
||||
|
||||
API DTO를 바꿨다면 먼저 생성 산출물을 갱신한다.
|
||||
|
|
@ -279,6 +280,14 @@ VITE_API_BASE=http://127.0.0.1:8000 npm run e2e # 프록시 대신 API
|
|||
`POST /voice/speech`, Session 마이크 UI를 함께 검증한다. 브라우저 `<audio>.play()`가 차단된 조건에서도
|
||||
Web Audio buffer source 재생이 시작되는지와 Session 마이크 UI가 `audio_end`에 browser voice
|
||||
activity/silence 메타를 싣는지 확인한다.
|
||||
- 2026-07-30 세션 음성/지연 focused 검증: 실제 로컬 P1 브라우저에서 응답 생성 중 textarea가 enabled이고
|
||||
다음 질문 초안이 보존되며, 음성 준비/재생 중에도 보내기가 enabled인 것을 확인했다. 이전 full API 2턴은
|
||||
fast-loop evaluator를 직렬로 기다려 완료가 24.17/24.57초였지만, 사후 평가 분리 뒤 실제 UI 응답·전송 해제는
|
||||
첫 턴 9.58초, 상주 세션 연속 턴 6.96초였다. `test_session_turn_persistence.py`는 느린 평가 훅이 끝나기 전에
|
||||
SSE `done`이 반환되고 이후 normalized 평가가 learner turn에 붙는 계약을 고정한다. Higgs API smoke는
|
||||
`higgs-audio-v3-tts-4b`, 24kHz mono WAV 362,924 bytes/7.56초, provider/model 헤더와 synthetic-seed-only
|
||||
reference policy를 확인했다. 검증: backend 432 passed, gateway 44 passed, typecheck/API types/build,
|
||||
session text stream 1 passed, voice skip/draft 1 passed.
|
||||
- 2026-07-13 focused 검증: `PLAYWRIGHT_PORT=5269 npx playwright test e2e/voice-success.spec.ts --project=chromium-single-run --workers=1 --grep "drives one voice turn"` **1 passed**. 같은 로그인에서 텍스트 턴 저장→소유 회기/턴 기반 `/voice/speech`→OpenAI speech 요청→Web Audio buffer 재생 시작을 확인하고, 별도 새 회기에서 마이크 PCM/STT→AI reply→TTS chunk/`tts_end` 경로가 유지되는지 검증한다. 백엔드 voice focused는 **32 passed**이며, 운영 키 직접 smoke는 `gpt-4o-mini-tts`가 98,133-byte MP3(11.68초)를 반환했다.
|
||||
- 2026-07-01 focused 검증: `PLAYWRIGHT_PORT=5205 npx playwright test e2e/session-persistence.spec.ts --project=chromium-single-run --workers=1` **7 passed**. 실제 브라우저 `openSessionStream()` → `/sessions/{id}/stream` → DB-backed `/review` 축어록 저장 경로, AI 튜터 코칭 이력 저장/재로딩, WebSocket `stt_result` 음성 비언어 메타데이터, Session 마이크 UI가 생성한 voice activity/silence 메타, Phase 3 pre/post 점수의 DB-backed 저장/재조회, 그리고 세션 종료 background deep 평가가 durable DB row로 저장되어 교수자 리뷰가 `평가 완료`로 전환되는지 검증한다. AI 튜터 코칭 이력 검증은 `POST /live-coach` 응답과 DB-backed history payload의 `status=ready`, `latency_ms>0`도 확인해 규칙 기반 `degraded` fallback 200 응답이 정상 AI 코칭으로 통과하지 못하게 한다.
|
||||
- 2026-07-01 추가 DB-backed 검증: `PLAYWRIGHT_PORT=5238 npx playwright test e2e/session-persistence.spec.ts --project=chromium-single-run --workers=1 --grep "finishes session end evaluation"` **1 passed**. 같은 자동 종료 평가 row가 `/teacher/dashboard`의 `recent_sessions`에서도 `evaluation_status=ready`, `review_ready=true`, `supervisor_state=평가 완료`로 반영되는지 실제 DB/API/엔진으로 검증한다.
|
||||
|
|
@ -334,12 +343,37 @@ VITE_API_BASE=http://127.0.0.1:8000 npm run e2e # 프록시 대신 API
|
|||
|
||||
`e2e/public-auth-turn.spec.ts`와 `e2e/public-admin-visual.spec.ts`는 공개 사이트
|
||||
(`https://vignette.chanpaca.net`)를 직접 타격하는 옵트인 스모크로, 로컬 웹 서버를 띄우지 않는다.
|
||||
관리자 시각 스모크는 운영 홈·사용자·권한·티켓의 본문 노출과 브라우저 `pageshow` 탭 복원 뒤
|
||||
스크롤/heading 가시성을 함께 검증한다. 절차는 `apps/web/e2e/README.md` 참고
|
||||
관리자 시각 스모크는 운영 홈·AI 운영·사용자·권한·티켓의 본문 노출, primary learner 화면의
|
||||
`운영 콘솔` 복귀, 브라우저 `pageshow` 탭 복원 뒤 실제 내부 `.vg-main.scrollTop=0`과 heading 가시성을
|
||||
함께 검증한다. document `window.scrollY`만 검사하면 관리자 셸의 실제 스크롤 잔류를 놓치므로 금지한다.
|
||||
로컬 `admin.spec.ts`의 `EasyList cosmetic filters` 회귀는 공식 목록에 있는 옛 `.ad-root`와
|
||||
`.ad-section` 숨김 규칙을 그대로 주입한 뒤에도 중립 `[data-vignette-admin-root]`와 운영 홈 heading이
|
||||
보이는지 확인한다. API 200이나 DOM 존재만으로 이 검증을 대신하면 광고 차단기 silent blank를 놓친다.
|
||||
`npm run check:cosmetic-filter-safety`는 `src/**/*.{ts,tsx,css}`와 `index.html`을 검사해
|
||||
`ad-*`, `ads-*`, `advert*`, `sponsor*` class/id namespace가 프로덕션 코드에 다시 들어오면 빌드를
|
||||
즉시 실패시킨다. 탐지기 자체의 양성·음성 fixture는 매 실행마다 먼저 검증하며,
|
||||
`npm run check:cosmetic-filter-safety:self-test`로 따로 실행할 수도 있다. 이 검사는 `npm run build`와
|
||||
`npm run lint` 앞단에 포함되므로 `scripts/start-public-runtime.ps1`의 실제 웹 빌드도 우회하지 못한다.
|
||||
공개 `public-admin-visual.spec.ts` 역시 같은 EasyList 규칙을 첫 paint부터 적용한 상태로 관리자 5경로의
|
||||
heading/root 실제 rect·computed visibility, legacy class 0, watchdog/console 오류 0을 확인한다.
|
||||
절차는 `apps/web/e2e/README.md` 참고
|
||||
(`E2E_PUBLIC_AUTH=1`, `npx playwright codegen ... --save-storage`로 인증 상태 캡처 후
|
||||
`E2E_PUBLIC_STORAGE_STATE` 재사용). 캡처한 storage state에는 API 세션 쿠키가 들어 있으니
|
||||
민감 정보로 취급한다.
|
||||
|
||||
### 3.8 배포 전환 청크 복구 스모크(선택)
|
||||
|
||||
`e2e/chunk-recovery-preview.spec.ts`는 프로덕션 빌드의 로그인 lazy 청크 첫 요청을 강제로 실패시켜
|
||||
문서가 정확히 한 번만 다시 로드되고 로그인 라우트가 정상 렌더되는지 검증한다. 로컬 `vite preview` 또는
|
||||
공개 도메인을 `PLAYWRIGHT_BASE_URL`로 지정하고 아래처럼 실행한다.
|
||||
|
||||
```powershell
|
||||
$env:E2E_PREVIEW_BUILD = "1"
|
||||
$env:PLAYWRIGHT_SKIP_WEB_SERVER = "1"
|
||||
$env:PLAYWRIGHT_BASE_URL = "http://127.0.0.1:5262" # 또는 https://vignette.chanpaca.net
|
||||
npx playwright test e2e/chunk-recovery-preview.spec.ts --project=chromium-single-run --workers=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 전체 검증 순서 권장안 (로컬)
|
||||
|
|
@ -356,9 +390,15 @@ cd apps/web && npm run typecheck && npm run build
|
|||
cd apps/web && npm run e2e
|
||||
```
|
||||
|
||||
엔진 턴 생성까지 보려면(음성/세션 MVP 등 일부 `@single-run`) 별도로 엔진 게이트웨이를
|
||||
포트 9099에 띄운다(`ENGINE_MODE=claude_cli`). 게이트웨이가 없으면 `/health`의 `engine:false`
|
||||
이고, 실제 턴 생성 시나리오는 실패한다. 레이아웃/시각 게이트는 게이트웨이 없이도 통과한다.
|
||||
엔진 턴 생성이나 관리자 모델 저장까지 보려면(음성/세션 MVP 등 일부 `@single-run`) 현재 코드의
|
||||
엔진 게이트웨이를 포트 9099에 띄운다. DB의 `admin_engine_config.engine_url`이 오래 떠 있던 구형
|
||||
게이트웨이를 가리키면 `/admin/engine-capabilities`가 404/503이므로 프로세스를 새 코드로 재기동해야 한다.
|
||||
게이트웨이가 없으면 `/health`의 `engine:false`이고 실제 턴 생성·모델 저장 시나리오는 실패한다.
|
||||
레이아웃/시각 게이트는 게이트웨이 없이도 통과한다.
|
||||
|
||||
공급자 실증은 capability만 확인하지 말고 최소 한 번 실제 고유 응답까지 확인한다. Codex는
|
||||
`gpt-5.6-terra` / Medium, Agy는 `gemini-3.6-flash-high` / High가 목록 기본값과 실행 결과 양쪽에서
|
||||
일치해야 한다. Anthropic은 실제 키가 없는 환경에서 unavailable·저장 거부가 정상이다.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue