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

# OpenAI Responses/workspace 테스트 시나리오 분해

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

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

## 배경

첫 OpenAI 분해 뒤 server_test.go에는 Responses와 workspace/cancel/route 시나리오가 provider 계열과 함께 남는다. 두 번째 단계는 3,194~4,479줄을 분리해 Responses 계약을 작은 read set으로 만든다.

## 사용자 리뷰 요청 흐름

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


## 분석 결과

### 읽은 파일

- 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 결과는 허용하지 않는다.

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

동작 변경은 없다. 기존 Responses/workspace/cancel 테스트를 그대로 옮기며 package 전체 Test 226개를 보존한다.

### 심볼 참조

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

### 분할 판단

공유 task group은 agent-task/m-agent-readable-repository-refactor다. 이 디렉터리의 +01은 01_openai_auth_chat/complete.log를 요구한다. 현재 predecessor complete.log는 없으므로 구현 시작 전 runtime이 이를 충족해야 한다. 03+02_openai_provider_tools가 이 작업 뒤 원본을 최종 제거한다.

### 범위 결정 근거

server_test.go의 기존 3,194~4,479줄에 해당하는 Responses, metadata/workspace, cancellation, route catalog만 이동한다. provider pool/tunnel/tool 후반부와 production 소스는 제외한다.

### 빌드 등급

local-G07: 같은 대형 파일의 두 번째 기계적 분해이며 protocol별 fixture 결합을 유지해야 한다.

## 구현 체크리스트

- [x] [TEST-1] Responses, metadata/workspace, cancel/route 테스트를 책임별 파일로 옮기고 Test 목록 226개 및 package test 통과를 보존한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [TEST-1] Responses/workspace/cancel 시나리오 파일 분리

- 문제: apps/edge/internal/openai/server_test.go:3194~4479에 Responses shape, metadata/workspace, cancel, route catalog가 연속 배치되어 feature-local 탐색이 어렵다.
- 해결 방법:

~~~text
Before
apps/edge/internal/openai/server_test.go:3194 func TestResponsesDispatchesNonStreamingRequest(...)
apps/edge/internal/openai/server_test.go:3342 func TestChatCompletionsMetadataContractAndWorkspace(...)
apps/edge/internal/openai/server_test.go:3817 func TestCollectRunResultTimesOut(...)

After
responses_handler_test.go        Responses shape/strict output
workspace_metadata_test.go       chat/Responses metadata와 workspace
cancellation_routes_test.go      cancel/timeout와 route catalog
~~~

- 수정 파일 및 체크리스트:
  - [x] apps/edge/internal/openai/server_test.go: 해당 구간만 제거하고 provider 후반부를 유지한다.
  - [x] apps/edge/internal/openai/responses_handler_test.go: Responses handler 시나리오를 옮긴다.
  - [x] apps/edge/internal/openai/workspace_metadata_test.go: metadata/workspace 시나리오를 옮긴다.
  - [x] apps/edge/internal/openai/cancellation_routes_test.go: cancel/timeout/route 시나리오를 옮긴다.
- 테스트 작성: 추가 테스트는 작성하지 않는다. 기존 Test 이름과 assertion을 그대로 유지하고 package 목록 수로 누락을 검출한다.
- 중간 검증:

~~~bash
gofmt -w apps/edge/internal/openai/*_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 성공, top-level Test 226개.

## 의존 관계 및 구현 순서

1. agent-task/m-agent-readable-repository-refactor/01_openai_auth_chat/complete.log가 생성된 뒤 시작한다.
2. 이 plan은 디렉터리 이름에 없는 추가 predecessor를 요구하지 않는다.

## 계획 대비 변경 사항

원본 PLAN의 라인 참조(3194~4479)와 "After"分组은 predecessor(01+01_openai_auth_chat) split 이전 파일 구조를 기반으로 작성되었다. predecessor가 Responses shape/strict output, metadata/workspace, cancel/timeout/route catalog 함수를 이미 이동시킨 후, 현재 잔여 26개 함수는 provider pool routing/tool validation/metadata classification/assembled logs 영역이다.

현실 반영:
- 실제 이동 범위: server_test.go 라인 3209~4531 (1323줄, 26개 Test 함수)
- 응답分组: `responses_handler_test.go`(Responses metadata + assembled logs, 6개), `workspace_metadata_test.go`(provider pool 선택, 10개), `cancellation_routes_test.go`(chat provider pool + tool validation, 10개)

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| apps/edge/internal/openai/server_test.go | TEST-1 |
| apps/edge/internal/openai/responses_handler_test.go | TEST-1 |
| apps/edge/internal/openai/workspace_metadata_test.go | TEST-1 |
| apps/edge/internal/openai/cancellation_routes_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 ]
~~~

기대 결과: fresh package test PASS와 Test 226개 보존.

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