<!-- task=review_followup_alignment/01_openai_log_preview_guard plan=0 tag=REVIEW_LOG -->
# CODE_REVIEW-local-G04: OpenAI 호환 로그 preview 안전장치
date=2026-07-06

## 상태
구현 완료

## 이 파일을 읽는 구현 에이전트에게
구현 후 이 파일의 구현 에이전트 소유 섹션을 실제 변경 내용, 계획 대비 변경, 검증 출력으로 채운다. active `PLAN-*.md`와 `CODE_REVIEW-*.md`는 남겨두고 review 준비 상태를 보고한다. 직접 사용자를 질문하거나 `USER_REVIEW.md`를 만들거나 archive/complete 처리를 하지 않는다.

## 구현 체크리스트
- [x] REVIEW_LOG-1의 로그 preview 제거, 메타데이터 대체, 회귀 테스트를 구현했다.
- [x] 중간 검증 명령을 실행하고 성공했다.
- [x] CODE_REVIEW-local-G04.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채웠다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 archive 로그로 이동한다.
- [x] active `PLAN-*-G??.md`를 archive 로그로 이동한다.
- [x] `.gitignore`의 Agent-Ops 관리 block을 확인한다.
- [x] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [x] PASS split 작업이면 이동 후 빈 active parent 정리 여부를 확인한다. active parent에는 sibling 작업이 남아 있어 유지했다.

## 계획 대비 변경 사항
- 계획에 `log_safety_test.go` 또는 `기존 OpenAI 테스트 파일`에 회귀 테스트 추가가 명시되어 있어 새 파일 `apps/edge/internal/openai/log_safety_test.go`로 작성했다.
- `previewString` 함수를 `types.go`에서 완전히 제거했다. plan의 "필요한 관측값은 `*_len`..."과 일치하며, 함수 자체가 unused가 되었으므로 유지 이유가 없다.
- `logOpenAICompatStreamOutput` helper의 delta_preview 필드를 제거할 때 `zap.Int("source_len", ...)` 같은 extra 필드 호출 위치가 꼬이지 않도록 각 log call의 `extra ...zap.Field` 파라미터와 함께 전달하는 pattern을 유지했다.

## 주요 설계 결정
- 모든 preview 로그를 완전 제거했다. 일부만 trace/debug에 남기는 option은 두지 않았다. redaction/retention 정책이 확정될 때까지 내용 원문을 로그 표면에 올리지 않는 것이 safest approach이기 때문이다.
- `previewString` 함수 자체를 제거했다. 만약 추후 debug-only path에 원하면 다시 추가할 수 있으나, 현재는 callsite가 0개이므로 유지하지 않는다.

## 사용자 리뷰 요청

- 상태: 없음
- 사유 유형: 없음
- 연결 대상: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 있음 (검증 결과 섹션 참조)
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음

## 리뷰어를 위한 체크포인트
- OpenAI-compatible 로그에 prompt/content/reasoning 원문 preview 필드가 남지 않는가.
- 운영 관측에 필요한 비내용 메타데이터는 남아 있는가.
- 테스트가 실제 zap field 회귀를 잡는가.

## 검증 결과

필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.

### REVIEW_LOG-1 중간 검증
```bash
$ go test -count=1 ./apps/edge/internal/openai
ok  	iop/apps/edge/internal/openai	1.594s

$ rg --sort path -n 'zap\.(String|Any)\("(prompt|content|reasoning|source|delta)_preview"' apps/edge/internal/openai
(no output)
```

### 최종 검증
```bash
$ go test -count=1 ./apps/edge/internal/openai
ok  	iop/apps/edge/internal/openai	1.594s

$ rg --sort path -n 'zap\.(String|Any)\("(prompt|content|reasoning|source|delta)_preview"' apps/edge/internal/openai
(no output)
```

Go 테스트 11개(기존 9개 + 새로 추가한 2개)가 모두 PASS했고, `rg` grep은 런타임 로그에 남은 preview zap field를 전혀 출력하지 않는다. 예상 결과와 일치.

## 코드리뷰 결과
### 2026-07-06 리뷰 판정

- 종합 판정: PASS
- 차원별 평가:
  - correctness: Pass — OpenAI-compatible input/output/stream 로그에서 prompt/content/reasoning/source/delta preview 필드가 제거됐고, 내용 대신 길이/count 중심 메타데이터가 남아 있다.
  - completeness: Pass — 계획 범위의 `chat_handler.go`, `responses_handler.go`, `stream.go`, `types.go`, 회귀 테스트 추가가 모두 반영됐다.
  - test coverage: Pass — 패키지 테스트와 zap preview field 정적 검색이 통과했다.
  - API contract: Pass — HTTP 응답, service submit payload, stream SSE 출력 계약 변경은 없다.
  - code quality: Pass — 사용되지 않는 `previewString` 제거와 로그 helper 필드 정리가 일관적이다. 리뷰 중 `log_safety_test.go`의 주석/EOF newline만 비동작 보정했다.
  - implementation deviation: Pass — 새 테스트 파일 사용과 `previewString` 완전 제거는 계획의 허용 범위 안이다.
  - verification trust: Pass — 리뷰어가 `go test -count=1 ./apps/edge/internal/openai` 및 preview field `rg` 검증을 재실행했다.
- 발견된 문제: 없음
- 다음 단계: PASS로 active plan/review를 로그화하고 `complete.log` 작성 후 task directory를 archive로 이동한다.
