# [fix] PR #118 e2e 회귀 — 502 시나리오 "연결 실패" 토스트 2중 렌더

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "src/pages/InfoKeyword.tsx"
    - "src/**/__tests__/**"
    - "tests/e2e/keyword-analysis-info-generate.spec.ts"
  forbidden_paths:
    - "extension/**"
    - "server/**"
    - ".github/**"
    - "src/lib/**"
  commands:
    - "npx vitest"
    - "npx playwright"
    - "npx tsc"
    - "git"
  merge_policy: "none"
  ttl_hours: 8
```
> ★ merge_policy=none — PR OPEN 유지. 브랜치 **`task/task-2833-dev2`**(PR #118)에 이어서 커밋(새 PR 금지).

## 문제 (실측)
PR #118(폴링 상한 동적화, task-2833)이 e2e 회귀 유발. **main(PR#117)에서 e2e SUCCESS였는데 PR#118에서 FAILURE.**
- 실패 테스트: `tests/e2e/keyword-analysis-info-generate.spec.ts:382` **시나리오2: 502 에러 → 한국어 에러 토스트**.
- 에러: `strict mode violation: getByText("인포키워드 서버 연결에 실패했습니다") resolved to 2 elements` (line 405 `toBeVisible`).
- 즉 502 시나리오에서 그 텍스트가 **2번 렌더**됨(원래 1번 기대). 재시도(retry #1)에도 실패 = 결정적 회귀(flaky 아님).
- 원인 후보: PR#118이 **폴링 루프 + catch 에러핸들링**을 변경 → 502 상태응답마다 공유 `apiFetch`가 "연결 실패" 토스트를 띄우는데, **더 긴 동적 상한/재시도로 토스트가 중복 누적** 또는 analyze catch + status poll 이중 토스트.

## 작업
1. **원인 규명**: e2e 로컬 재현(`npx playwright test tests/e2e/keyword-analysis-info-generate.spec.ts:382`). 502 시 "연결 실패" 토스트가 **왜 2번** 뜨는지(폴링 루프가 502에 계속 poll하며 매회 토스트? analyze catch + poll 이중?).
2. **수정**: 502/연결에러 시 **토스트 1회만**(중복 억제 — 예: 에러 시 폴링 중단, 또는 동일 에러 토스트 dedup). **폴링 상한 동적화(원래 PR#118 기능)는 유지** — 그건 정상. 사용자엔 502 에러가 **한 번만** 명확히.
3. **거짓 5분 실패 수정(원래 목적)은 보존**: 정상(성공) 경로에서 상한이 키워드수 비례로 커지는 것 유지.

## 검증 (전부 통과)
- `npx playwright test tests/e2e/keyword-analysis-info-generate.spec.ts` → **시나리오2 PASS**(연결 실패 토스트 정확히 1개), 시나리오1·3 회귀 0.
- 폴링 상한 동적화 단위테스트(task-2833 추가분) 유지.
- `npx tsc` 클린 · InfoKeyword 관련 vitest 회귀 0.

## 완료
- `src/pages/InfoKeyword.tsx`(+테스트/e2e) 외 변경 0 (`git diff --stat`). `src/lib/apiFetch` 건드리지 마라(공유).
- **dev6 금지** — dev2(원 담당). worktree finish → push(PR #118 반영·새 PR 금지) → ANU 독립검증. **머지 금지**(merge_policy none).
- **ANU callback**(UTF-8 ≤3900 bytes, envelope).
