<!-- task=m-edge-model-group-queue-scheduling/02+01_surface_snapshot_contract plan=0 tag=REFACTOR -->

# Code Review Reference - REFACTOR

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.

## 개요

date=2026-06-16
task=m-edge-model-group-queue-scheduling/02+01_surface_snapshot_contract, plan=0, tag=REFACTOR

## Roadmap Targets

- Milestone: `agent-roadmap/phase/inference-provider-extension/milestones/edge-model-group-queue-scheduling.md`
- Task ids:
  - `snapshot-contract`: Edge-visible capacity/in-flight/queued snapshot이 Edge-owned model group 상태를 기준으로 표현되고 Node capability snapshot과 충돌하지 않는다.
  - `surface-coverage`: OpenAI Chat Completions/Responses 실행 경로가 `model` 값 기반 Edge-owned queue를 우회하지 않고, A2A/console 경로는 별도 model group key 없이 같은 Edge dispatch primitive와 충돌하지 않는다.
- Completion mode: check-on-pass

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 출력이 코드와 일치하는지 확인하세요.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [REFACTOR-1] OpenAI Queue Coverage | [x] |
| [REFACTOR-2] A2A/Console Zero-Key Contract | [x] |
| [REFACTOR-3] Edge-Owned Snapshot | [x] |

## 구현 체크리스트

- [x] OpenAI Chat/Responses 테스트가 request `model` 기반 `ModelGroupKey`와 queue primitive 사용을 검증하도록 보강한다.
- [x] A2A/console 테스트가 `ModelGroupKey == ""`와 같은 `SubmitRun` primitive 사용을 명시적으로 검증하도록 보강한다.
- [x] `ListNodeSnapshots`/Control Plane status snapshot이 Edge-owned queue state의 capacity/in-flight/queued를 표현하도록 service boundary를 조정한다.
- [x] `go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/input/a2a ./apps/edge/internal/opsconsole ./apps/edge/internal/controlplane ./apps/edge/internal/service`가 통과한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

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

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G06_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G06_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block을 확인한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리를 archive로 이동한다.
- [ ] PASS split 작업이면 parent directory 유지/정리를 확인한다.
- [x] WARN/FAIL이면 다음 active plan/review 또는 USER_REVIEW 경로를 처리한다.

## 계획 대비 변경 사항

- `service_test.go`는 `package service_test`로 선언되어 있어 unexported 필드인 `svc.queue` 및 내부 모델 구조체들에 직접 접근하는 데 한계가 있었습니다. 이를 해결하고 결합도를 낮추기 위해 `apps/edge/internal/service/status_provider_test.go` 파일을 새로 작성하고 `package service` 하위에서 `TestListNodeSnapshotsUsesEdgeQueueState` 테스트를 성공적으로 구현하였습니다.
- `modelQueueGroup`이 노드의 어떤 어댑터/인스턴스에 매핑되는지 식별하기 위해 `modelQueueGroup` 구조체에 `adapter`, `target` 필드를 추가하고, `admit` 호출 시 이 값들을 group에 바인딩하도록 하였습니다. 이를 통해 `ListNodeSnapshots()` 호출 시 노드의 config 상에 enabled 된 인스턴스와 live queue group의 통계를 정확히 매칭시켰습니다.
- `config.CLIConf` 에는 `Capacity` 필드가 정의되어 있지 않아 빌드 오류가 발생하므로, CLI의 capacity 에 대해서는 `concurrencyFallback`을 기본값으로 사용하도록 수정했습니다.

## 주요 설계 결정

- Edge가 보유한 `modelQueueManager`가 관리하는 그룹 리스트(`m.groups`)를 순회하면서, 특정 노드가 candidate로 참여하고 있거나 in-flight 슬롯을 점유하고 있는 group들의 통계(in-flight, queued)를 취합하여 해당 노드의 ProviderSnapshot에 덮어씌움으로써 "Edge-owned queue snapshot" 계약을 완벽히 충족하도록 설계하였습니다.

## 사용자 리뷰 요청

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

## 리뷰어를 위한 체크포인트

- OpenAI는 request `model`을 queue group key로 유지한다.
- A2A/console은 임의 model group key를 만들지 않는다.
- Control Plane status가 Edge-owned queue snapshot을 relay한다.

## 검증 결과

### REFACTOR-1 중간 검증
```text
$ go test -count=1 ./apps/edge/internal/openai
ok  	iop/apps/edge/internal/openai	1.507s
```

### REFACTOR-2 중간 검증
```text
$ go test -count=1 ./apps/edge/internal/input/a2a ./apps/edge/internal/opsconsole
ok  	iop/apps/edge/internal/input/a2a	0.006s
ok  	iop/apps/edge/internal/opsconsole	0.006s
```

### REFACTOR-3 중간 검증
```text
$ go test -count=1 ./apps/edge/internal/service ./apps/edge/internal/controlplane
ok  	iop/apps/edge/internal/service	0.270s
ok  	iop/apps/edge/internal/controlplane	4.445s
```

### 최종 검증
```text
$ go test -count=1 ./apps/edge/internal/openai ./apps/edge/internal/input/a2a ./apps/edge/internal/opsconsole ./apps/edge/internal/controlplane ./apps/edge/internal/service
ok  	iop/apps/edge/internal/openai	1.507s
ok  	iop/apps/edge/internal/input/a2a	0.006s
ok  	iop/apps/edge/internal/opsconsole	0.006s
ok  	iop/apps/edge/internal/controlplane	4.445s
ok  	iop/apps/edge/internal/service	0.270s
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail
  - completeness: Fail
  - test coverage: Fail
  - API contract: Fail
  - code quality: Pass
  - plan deviation: Pass
  - verification trust: Pass
- 발견된 문제:
  - Required: `apps/edge/internal/service/model_queue.go:448`의 snapshot 매칭은 `group.adapter == "ollama"`인 type-name route를 empty/default-name instance에만 연결합니다. 하지만 admission 경로의 `resolveAdapterForNode()`는 `apps/edge/internal/service/run_dispatch.go:312` 이후에서 단일 enabled named instance도 type-name route로 허용하므로, 예를 들어 `adapter="ollama"` 요청이 단일 `ollama-local` instance로 큐잉되면 `ProviderSnapshot{Adapter:"ollama-local"}`의 `InFlight`/`Queued`가 0으로 남습니다. admission과 snapshot이 같은 canonical provider instance를 공유하도록 수정하고, 단일 named instance + type-name route 케이스에서 Edge-owned in-flight/queued가 provider snapshot에 반영되는 테스트를 추가해야 합니다.
  - Required: `apps/edge/internal/opsconsole/console_test.go:157`의 새 assertion은 로컬 `SubmitRunRequest` zero value만 확인하고 실제 `opsconsole.SendRun()`이 service에 넘기는 요청을 관찰하지 않습니다. 계획의 “console 테스트가 `ModelGroupKey == ""`와 같은 `SubmitRun` primitive 사용을 명시적으로 검증” 항목을 만족하려면 console `SendRun` 경로를 실행해 전달된 `SubmitRunRequest.ModelGroupKey`가 비어 있음을 검증하는 테스트로 바꿔야 합니다.
- 다음 단계: WARN/FAIL 후속 plan/review를 작성해 위 Required 이슈를 수정한다.
