<!-- task=m-agent-readable-repository-refactor/04_core_config_tests plan=1 tag=REVIEW_TEST -->

# Core config 테스트 책임 배치 보정

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

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

## 배경

첫 리뷰에서 107개 테스트 본문과 package 검증은 보존됐지만 CLI와 provider 책임의 테스트 두 개가 서로 반대 파일에 배치된 것을 확인했다. 테스트 동작은 바꾸지 않고 파일명과 테스트 책임만 일치시켜 원래 분해 목표를 완성한다.

## 사용자 리뷰 요청 흐름

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

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-agent-readable-repository-refactor/04_core_config_tests/plan_local_G06_0.log`
- Prior review: `agent-task/m-agent-readable-repository-refactor/04_core_config_tests/code_review_local_G06_0.log`
- Verdict: FAIL (review 1)
- Findings: Required 1, Suggested 0, Nit 0; 분할 경계의 주석 위치 드리프트는 리뷰어가 직접 보정했다.
- Affected files: `packages/go/config/edge_cli_config_test.go:139`, `packages/go/config/provider_catalog_config_test.go:297`
- Verification evidence: 원본/분할본 107개 `Test*` 함수 SHA-256 일치, `go test -count=1 ./packages/go/config` PASS, `go test -count=1 ./packages/go/...` PASS, 1,000줄 초과 테스트 없음.
- Allowed narrow reread: 위 `plan_local_G06_0.log`, `code_review_local_G06_0.log`만 필요할 때 읽는다.
- Roadmap carryover: prior artifacts에 `Roadmap Targets`가 없으므로 없음.

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-spec/runtime/provider-pool-config-refresh.md`
- `agent-contract/inner/edge-config-runtime-refresh.md`
- `packages/go/config/config.go`
- `packages/go/config/edge_cli_config_test.go`
- `packages/go/config/edge_openai_config_test.go`
- `packages/go/config/edge_runtime_config_test.go`
- `packages/go/config/node_config_test.go`
- `packages/go/config/provider_catalog_config_test.go`
- `packages/go/config/provider_catalog_validation_config_test.go`
- `HEAD:packages/go/config/config_test.go`
- `agent-task/m-agent-readable-repository-refactor/04_core_config_tests/plan_local_G06_0.log`
- `agent-task/m-agent-readable-repository-refactor/04_core_config_tests/code_review_local_G06_0.log`

### SDD 기준

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

### 테스트 환경 규칙

`test_env=local`. `agent-test/local/rules.md`와 `agent-test/local/platform-common-smoke.md`를 읽었다. 공통 Go package 변경의 대상 package test와 `go test ./packages/go/...`를 적용하고, fresh 결과가 필요하므로 `-count=1`을 사용한다. production/config schema 변경이 없는 테스트 파일 이동이므로 Edge/Node full-cycle은 영향 범위에 없으며 수행하지 않는다.

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

동작 변경은 없다. 기존 107개 테스트 함수 본문을 그대로 유지하므로 새 테스트는 필요하지 않으며, 함수별 SHA-256 대조와 fresh package test로 이동 중 손실을 검증한다.

### 심볼 참조

production 심볼 rename/remove는 없다. `TestLoadEdge_OllamaContextSize`와 `TestLoadEdge_CodexAppServerDefaultProfile`의 파일 위치만 바꾼다.

### 분할 판단

split 정책을 재평가했다. 기존 Milestone split subtask `04_core_config_tests` 안의 두 파일에서 테스트 두 개를 교환하는 하나의 기계적 보정이며 동일 package·동일 검증·동일 위험을 가진다. API/소유권/테스트 전략 경계가 추가로 갈리지 않고 별도 plan으로 나누면 동일 검증을 중복하므로 이 subtask 안의 단일 follow-up plan이 안전하다.

### 범위 결정 근거

`edge_cli_config_test.go`와 `provider_catalog_config_test.go`의 두 테스트 위치만 바꾼다. `config.go`, 다른 테스트 본문, config schema, spec/contract, sibling task 파일은 수정하지 않는다. 첫 리뷰에서 적용한 주석 위치 보정은 현재 상태로 유지한다.

### 빌드 등급

`local-G03`: 두 테스트 블록을 같은 package 안에서 책임 파일로 옮기는 제한적이고 결정적인 test-only 변경이며 로컬 명령으로 완전히 검증할 수 있다.

## 구현 체크리스트

- [x] [REVIEW_TEST-1] `TestLoadEdge_OllamaContextSize`를 provider catalog 파일로, `TestLoadEdge_CodexAppServerDefaultProfile`을 CLI 파일로 옮기고 함수 본문·107개 테스트·1,000줄 제한·package test를 보존한다.
- [x] CODE_REVIEW-local-G03.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채웠다.

### [REVIEW_TEST-1] CLI/provider 테스트 책임 배치 보정

- 문제:
  - `packages/go/config/edge_cli_config_test.go:139`의 `TestLoadEdge_OllamaContextSize`는 Ollama provider/adapter 설정 검증인데 CLI profile 파일에 있다.
  - `packages/go/config/provider_catalog_config_test.go:297`의 `TestLoadEdge_CodexAppServerDefaultProfile`은 CLI profile 검증인데 provider catalog 파일에 있다.
- 해결 방법:

~~~text
Before
edge_cli_config_test.go:139              TestLoadEdge_OllamaContextSize
provider_catalog_config_test.go:297      TestLoadEdge_CodexAppServerDefaultProfile

After
edge_cli_config_test.go                  TestLoadEdge_CodexAppServerDefaultProfile
provider_catalog_config_test.go          TestLoadEdge_OllamaContextSize
~~~

- 수정 파일 및 체크리스트:
  - [x] `packages/go/config/edge_cli_config_test.go`: Codex app-server profile 테스트를 받고 Ollama context 테스트를 제거한다.
  - [x] `packages/go/config/provider_catalog_config_test.go`: Ollama context 테스트를 받고 Codex app-server profile 테스트를 제거한다.
- 테스트 작성: 새 테스트를 작성하지 않는다. 기존 두 테스트의 함수 본문을 그대로 이동하는 test topology 보정이다.
- 중간 검증:

~~~bash
gofmt -w packages/go/config/edge_cli_config_test.go packages/go/config/provider_catalog_config_test.go
test "$(rg -l --sort path '^func TestLoadEdge_OllamaContextSize' packages/go/config/*_test.go)" = "packages/go/config/provider_catalog_config_test.go"
test "$(rg -l --sort path '^func TestLoadEdge_CodexAppServerDefaultProfile' packages/go/config/*_test.go)" = "packages/go/config/edge_cli_config_test.go"
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./packages/go/config | sed '/^ok[[:space:]]/d' | wc -l)" -eq 107 ]
~~~

기대 결과: 두 함수가 올바른 책임 파일에 하나씩 존재하고 top-level 테스트가 107개다.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/go/config/edge_cli_config_test.go` | REVIEW_TEST-1 |
| `packages/go/config/provider_catalog_config_test.go` | REVIEW_TEST-1 |

## 최종 검증

~~~bash
gofmt -w packages/go/config/edge_cli_config_test.go packages/go/config/provider_catalog_config_test.go
test ! -e packages/go/config/config_test.go
test "$(rg -l --sort path '^func TestLoadEdge_OllamaContextSize' packages/go/config/*_test.go)" = "packages/go/config/provider_catalog_config_test.go"
test "$(rg -l --sort path '^func TestLoadEdge_CodexAppServerDefaultProfile' packages/go/config/*_test.go)" = "packages/go/config/edge_cli_config_test.go"
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./packages/go/config | sed '/^ok[[:space:]]/d' | wc -l)" -eq 107 ]
GOCACHE=/tmp/iop-go-build-cache go test -count=1 ./packages/go/config
python3 -c "from pathlib import Path; p=Path('packages/go/config'); 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))"
diff -u <(git show HEAD:packages/go/config/config_test.go | perl -0777 -MDigest::SHA=sha256_hex -ne 'while (/^(func (Test\w+)\b.*?)(?=^func Test|\z)/msg) { my ($b,$n)=($1,$2); $b =~ s/(?:\s*\/\/[^\n]*)+\s*\z//s; $b =~ s/\s+\z//; print "$n ", sha256_hex($b), "\n"; }' | sort) <(perl -0777 -MDigest::SHA=sha256_hex -ne 'while (/^(func (Test\w+)\b.*?)(?=^func Test|\z)/msg) { my ($b,$n)=($1,$2); $b =~ s/(?:\s*\/\/[^\n]*)+\s*\z//s; $b =~ s/\s+\z//; print "$n ", sha256_hex($b), "\n"; }' packages/go/config/*_test.go | sort)
GOCACHE=/tmp/iop-go-build-cache go test -count=1 ./packages/go/...
~~~

기대 결과: 책임 배치가 일치하고 원본이 없으며 테스트 107개, 함수 본문 diff 없음, 1,000줄 초과 파일 없음, fresh config/common package test PASS다. Go test cache 결과는 허용하지 않는다.

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