<!-- task=m-agent-readable-repository-refactor/03+02_openai_provider_tools plan=0 tag=TEST -->

# OpenAI provider/tool 테스트 최종 분해

## 이 파일을 읽는 구현 에이전트에게

> 구현 후 검증을 실행하고 CODE_REVIEW 파일의 구현 에이전트 소유 섹션에 실제 메모와 출력을 채운 뒤 active 파일을 유지한 채 리뷰 준비 완료를 보고한다. 종결 판정, log rename, complete.log, archive 이동은 code-review 전용이다. 선택된 Milestone의 미해결 구현 잠금 결정이 실제 구현을 차단할 때만 CODE_REVIEW의 사용자 리뷰 요청에 연결 근거를 기록하고 중단한다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 request_user_input을 호출하거나 USER_REVIEW.md/complete.log를 만들지 않는다. 환경·secret·service, 일반 범위 조정, 후속 에이전트가 보완 가능한 증거 공백은 사용자 리뷰 사유가 아니다.

## 배경

앞선 두 단계가 auth/chat과 Responses/workspace를 제거하면 server_test.go에는 provider tunnel/pool, policy, tool validation, observability 시나리오가 남는다. 마지막 단계에서 이를 책임별 파일로 이동하고 원본 거대 파일을 제거해 openai-tests를 완료한다.

## 사용자 리뷰 요청 흐름

사용자 리뷰 요청은 선택된 Milestone의 구현 잠금 결정만 active review stub의 사용자 리뷰 요청 섹션에 기록한다. 섹션 형식은 agent-ops/skills/common/_templates/implementation-user-review-request-section.md를 따른다. 구현 중 직접 사용자 prompt는 금지하며, 요청의 타당성 검증과 USER_REVIEW.md 작성은 code-review가 소유한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md)
- Task ids:
  - `openai-tests`: OpenAI 서버 테스트를 기능 시나리오별 파일과 feature-local double로 분해
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- agent-roadmap/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md
- agent-test/local/rules.md
- agent-test/local/profiles/edge-smoke.md
- agent-test/local/profiles/testing-smoke.md
- agent-spec/input/openai-compatible-surface.md
- apps/edge/internal/openai/server_test.go

### SDD 기준

선택 Milestone은 SDD: 불필요다. 외부 API/proto/config schema와 runtime 책임 경계를 바꾸지 않는 동작 보존형 테스트 재배치라는 기록 사유를 적용한다.

### 테스트 환경 규칙

test_env=local. agent-test/local/rules.md와 edge-smoke/testing-smoke profile을 읽었다. 현재 checkout에서 GOCACHE=/tmp/iop-go-build-cache go test -count=1 ./apps/edge/internal/openai가 통과했다. 구조 리팩터링이므로 fresh package test와 Test 목록 수 226 보존을 계약으로 사용하며 cache 결과는 허용하지 않는다.

### 테스트 커버리지 공백

동작 변경은 없다. 기존 provider/tool 테스트 전부를 이동하고 top-level Test 226개, 파일 크기, fresh package test로 누락과 컴파일 회귀를 검출한다.

### 심볼 참조

운영 심볼의 rename/remove는 없다. 기존 Test* 이름과 package 경계를 그대로 유지한다.

### 분할 판단

공유 task group은 agent-task/m-agent-readable-repository-refactor다. +02는 02+01_openai_responses_workspace/complete.log를 요구하며 현재 미충족이다. 이 최종 sibling만 Roadmap Targets의 openai-tests를 check-on-pass 한다.

### 범위 결정 근거

server_test.go의 남은 provider/tool/observability 테스트와 직접 support만 다룬다. production OpenAI 모듈 분해는 modules Epic 범위이며 제외한다.

### 빌드 등급

local-G08: 3,600줄 이상 후반부, provider path별 fixture, 최종 원본 제거와 roadmap completion 검증을 함께 다룬다.

## 구현 체크리스트

- [ ] [TEST-1] provider tunnel/pool, policy, tool validation, observability 테스트를 분리하고 원본 제거, Test 226개, 1,000줄 초과 없음, package test 통과를 함께 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [TEST-1] provider/tool 시나리오 분리와 server_test.go 제거

- 문제: apps/edge/internal/openai/server_test.go:4480~8135에 provider dispatch/tunnel/policy, tool validation, logs/selection이 한 파일에 남아 있고 거대 fake 의존이 지속된다.
- 해결 방법:

~~~text
Before
apps/edge/internal/openai/server_test.go:4480 func TestHandleModelsProviderPoolCatalog(...)
apps/edge/internal/openai/server_test.go:6411 func TestChatCompletionsRetriesUnknownTextToolCallBeforeResponse(...)
apps/edge/internal/openai/server_test.go:7701 func TestProviderPoolDispatchLogObservationFields(...)

After
provider_dispatch_test.go         pool dispatch
provider_tunnel_test.go           chat/Responses tunnel
provider_policy_test.go           generation/thinking policy
provider_tool_validation_test.go  retry/schema validation
provider_observability_test.go    metadata/log fields
provider_selection_test.go        mixed pool selection
server_test.go                    removed
~~~

- 수정 파일 및 체크리스트:
  - [ ] apps/edge/internal/openai/server_test.go: 남은 테스트를 이동한 뒤 삭제한다.
  - [ ] apps/edge/internal/openai/provider_dispatch_test.go: pool dispatch 시나리오를 둔다.
  - [ ] apps/edge/internal/openai/provider_tunnel_test.go: provider tunnel 시나리오를 둔다.
  - [ ] apps/edge/internal/openai/provider_policy_test.go: generation/thinking policy를 둔다.
  - [ ] apps/edge/internal/openai/provider_tool_validation_test.go: tool retry/schema 검증을 둔다.
  - [ ] apps/edge/internal/openai/provider_observability_test.go: metadata/logging을 둔다.
  - [ ] apps/edge/internal/openai/provider_selection_test.go: mixed provider selection을 둔다.
  - [ ] apps/edge/internal/openai/server_test_support_test.go: 범용 fake를 실제 공통 함수 필드만 남기도록 축소한다.
- 테스트 작성: 추가 동작 테스트는 작성하지 않는다. 모든 기존 Test 이름/assertion을 보존하고 목록 수와 fresh test, LOC gate를 적용한다.
- 중간 검증:

~~~bash
gofmt -w apps/edge/internal/openai/*_test.go
test ! -e apps/edge/internal/openai/server_test.go
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./apps/edge/internal/openai | sed '/^ok[[:space:]]/d' | wc -l)" -eq 226 ]
~~~

기대 결과: 원본 삭제, gofmt 성공, Test 226개.

## 의존 관계 및 구현 순서

1. agent-task/m-agent-readable-repository-refactor/02+01_openai_responses_workspace/complete.log가 생성된 뒤 시작한다.
2. 디렉터리 이름의 predecessor 02 외 추가 의존성은 없다.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| apps/edge/internal/openai/server_test.go | TEST-1 |
| apps/edge/internal/openai/server_test_support_test.go | TEST-1 |
| apps/edge/internal/openai/provider_dispatch_test.go | TEST-1 |
| apps/edge/internal/openai/provider_tunnel_test.go | TEST-1 |
| apps/edge/internal/openai/provider_policy_test.go | TEST-1 |
| apps/edge/internal/openai/provider_tool_validation_test.go | TEST-1 |
| apps/edge/internal/openai/provider_observability_test.go | TEST-1 |
| apps/edge/internal/openai/provider_selection_test.go | TEST-1 |

## 최종 검증

~~~bash
GOCACHE=/tmp/iop-go-build-cache go test -count=1 ./apps/edge/internal/openai
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./apps/edge/internal/openai | sed '/^ok[[:space:]]/d' | wc -l)" -eq 226 ]
python3 -c "from pathlib import Path; p=Path('apps/edge/internal/openai'); bad=sorted((sum(1 for _ in f.open()),str(f)) for f in p.glob('*_test.go') if sum(1 for _ in f.open())>1000); print(bad); raise SystemExit(bool(bad))"
~~~

기대 결과: fresh package test PASS, Test 226개, 모든 OpenAI test 파일 1,000줄 이하.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
