# task-1768.1 완료 보고서 — 시나리오 검증 시스템 Phase 2

## SCQA

**S**: Phase 1 완료(task-1761.1, task-1762.1)로 impact_analyzer.py + scenario_runner.py + qc_verify.py 통합이 운영 중이며, subprocess/curl/pytest 타입 시나리오 실행이 가능하다.

**C**: E2E 렌더링 검증 부재로 "코드 존재 확인"까지만 가능하고, 실제 브라우저 환경에서의 UI 동작(드롭다운 가시성, 컴포넌트 렌더링)은 검증되지 않는다. Lv.3+ 작업의 품질 게이트가 불완전하다.

**Q**: Playwright E2E smoke test + 시나리오 시드 확충으로 UI 렌더링 검증 자동화가 가능한가?

**A**: 가능하다. scenario_runner.py에 `type: playwright` 지원을 추가하고, Firebase Auth 세션 관리(setup_auth.py), 15개 신규 시나리오 YAML 시드, Lv.3+ playwright 필수 게이트를 구현했다. pytest 12건 전부 통과(0.15s), subprocess 시나리오 11/11 통과.

---

## 산출물

### 신규 생성 파일
- `/home/jay/workspace/teams/shared/qc/auth/__init__.py`
- `/home/jay/workspace/teams/shared/qc/auth/setup_auth.py`
- `/home/jay/workspace/teams/shared/qc/scenarios/insuwiki/ui-components.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/insuwiki/dropdown-visibility.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/insuwiki/refine-flow.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/insuwiki/refine-progress.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/dashboard/load-tabs.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/dashboard/insuwiki-stats.yaml`
- `/home/jay/workspace/teams/shared/qc/scenarios/dashboard/refine-monitor.yaml`

### 수정 파일
- `/home/jay/workspace/teams/shared/qc/scenario_runner.py`
- `/home/jay/workspace/teams/shared/qc/tests/test_scenario_runner.py`

---

## 구현 상세

### 1. Playwright 러너 (scenario_runner.py)
- `_resolve_placeholders()`: 환경변수 기반 `{key}` → `SCENARIO_key` 치환
- `_execute_playwright_action()`: navigate/fill/click/assert_visible/assert_in_viewport/assert_not_visible/wait 7개 액션 지원
- `_run_playwright_scenario()`: storageState 인증, 실패 시 스크린샷 캡처
- `_run_scenario()` 분기: `type: playwright` → 별도 러너 위임 (기존 시그니처 유지)
- `verify()` 수정: level≥3에서 playwright 시나리오 없으면 WARN 반환

### 2. Firebase Auth 세션 관리 (setup_auth.py)
- `create_custom_token()`: Firebase Admin SDK로 custom token 생성
- `save_storage_state()`: Playwright에서 signInWithCustomToken 호출 → storageState.json 저장
- `verify_storage_state()`: 기존 세션 유효성 확인
- CLI: `--output`, `--uid`, `--base-url`, `--verify-only` 옵션

### 3. 시나리오 YAML 시드 (15개 신규)
- **insuwiki 10개**: 컴포넌트 렌더링(3), 드롭다운 가시성(2), 정제 흐름(3), 정제 polling(2)
- **dashboard 5개**: 대시보드 로드/탭(2), 통계(1), 모니터(2)
- playwright 타입 7개 + subprocess 타입 8개

### 4. qc_verify.py 연동
- 기존 scenario_gate verifier가 scenario_runner.verify() 호출 → Lv.3+ playwright 게이트 자동 적용
- Lv.1-2: playwright 시나리오 SKIP 허용 (기존 동작 유지)

---

## 테스트 결과

### pytest (12건 전부 통과)
```
tests/test_scenario_runner.py::test_run_scenarios_all_pass PASSED
tests/test_scenario_runner.py::test_must_fail_triggers_gate_fail PASSED
tests/test_scenario_runner.py::test_empty_scenarios_level3_fail PASSED
tests/test_scenario_runner.py::test_empty_scenarios_level1_skip PASSED
tests/test_scenario_runner.py::test_impact_filtering PASSED
tests/test_scenario_runner.py::test_execution_within_timeout PASSED
tests/test_scenario_runner.py::test_playwright_scenario_skipped_when_not_automatable PASSED
tests/test_scenario_runner.py::test_playwright_scenario_pass PASSED
tests/test_scenario_runner.py::test_playwright_scenario_assert_fail_returns_failed PASSED
tests/test_scenario_runner.py::test_verify_level3_requires_playwright PASSED
tests/test_scenario_runner.py::test_resolve_placeholders PASSED
tests/test_scenario_runner.py::test_verify_level2_skips_playwright_gate PASSED
12 passed in 0.15s
```

### 시나리오 실행 (서버 미실행 환경)
- subprocess 시나리오: insuwiki 7/7 통과, dashboard 4/4 통과
- playwright 시나리오: 5+2건 서버 미실행으로 예상된 실패 (localhost:3000/3001 미기동)

---

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **플레이스홀더 미해결** — `{test_doc_id}`가 URL에 그대로 인코딩되는 문제 → `_resolve_placeholders()` 함수 추가로 환경변수 기반 치환 구현
   - 수정: `scenario_runner.py:134-141` 신규 함수 + `:147` action 치환 호출
2. **Pyright sync_playwright 경고** — globals().get() 간접 참조로 "not accessed" 경고 → 직접 참조로 변경
   - 수정: `scenario_runner.py:182,186` — `globals().get("sync_playwright")` → `sync_playwright` 직접 사용
3. **Pyright 타입 에러** — `os.environ.get()` 반환 타입 `str | None` → `or m.group(0)` 패턴으로 해결
   - 수정: `scenario_runner.py:140`

### 범위 외 미해결 (2건)
1. **storageState TTL** — Firebase ID Token 1시간 만료 후 갱신 메커니즘 미구현. 범위 외 사유: Phase 3 운영 안정화 scope (context-notes.md OPEN 항목)
2. **Playwright ThreadPoolExecutor 병행** — playwright 시나리오가 ThreadPoolExecutor에서 실행됨. Playwright는 단일 스레드 권장. 범위 외 사유: 현재 시나리오 수가 적어 문제 없으나, 시나리오 20개+ 시 순차 실행 분리 필요 (Phase 3)

---

## 모델 사용 기록
- 토르(백엔드) / 작업: Playwright 러너 테스트+구현, setup_auth.py, verify() 게이트 / 모델: sonnet
- 프레이야(프론트엔드) / 작업: YAML 시나리오 시드 15개 작성 / 모델: sonnet

## 머지 판단
- **머지 필요**: No (시스템 작업, worktree 미사용)
- **브랜치**: N/A
- **워크트리 경로**: N/A
- **머지 의견**: shared/qc/ 디렉토리에 직접 반영 완료

## 세션 통계
- 총 도구 호출: 26회

### 수정 파일 목록
- /home/jay/workspace/teams/shared/qc/scenario_runner.py: 7회 (Edit)
- bash_cmd: 5회 (Bash)
- /home/jay/workspace/teams/shared/qc/tests/test_scenario_runner.py: 3회 (Edit)
- /home/jay/workspace/memory/reports/task-1768.1.md: 1회 (Write)
- /home/jay/workspace/memory/tasks/task-1768.1.md: 1회 (dispatch)
- /home/jay/workspace/teams/shared/qc/auth/__init__.py: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/auth/setup_auth.py: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/dashboard/insuwiki-stats.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/dashboard/load-tabs.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/dashboard/refine-monitor.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/insuwiki/dropdown-visibility.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/insuwiki/refine-flow.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/insuwiki/refine-progress.yaml: 1회 (Write)
- /home/jay/workspace/teams/shared/qc/scenarios/insuwiki/ui-components.yaml: 1회 (Write)

### 도구 사용 현황
- Edit: 10회
- Write: 10회
- Bash: 5회
- dispatch: 1회

