# Code Review: vLLM config contract (G06)

- **Milestone**: vLLM provider serving validation
- **Task**: `config-contract`
- **Build**: `local-G06`
- **Plan**: `PLAN-local-G06.md`

## 구현 에이전트 기록

### 선행 evidence 확인

- `01_spark_container` 디렉터리가 존재하지 않음 (선행 task 완료 후 정리됨으로 판단).
- 동등한 field evidence로 `agent-test/local/platform-common-smoke.md` 참고:
  - vLLM model 기준: checkpoint `nvidia/Qwen3.6-35B-A3B-NVFP4`, alias `qwen3.6:35b`
  - 이 값들은 plan에서 제시한 values와 일치하며 configs/edge.yaml 예시에 반영됨.

### [VLLM_CONFIG-1] vLLM OpenAI-compatible config example 정리

**변경 파일**: `configs/edge.yaml`

**변경 내용**:
- `openai.model_routes` 주석 영역에 vLLM OpenAI-compatible provider example 섹션 추가
- `provider="vllm"` 마킹, `adapter="openai_compat"` 사용, `target`에 served model ID (`nvidia/Qwen3.6-35B-A3B-NVFP4`)
- alias `qwen3.6:35b`, `max_queue: 10`, `queue_timeout_ms: 30000`
- headers 없음 (vLLM auth는 외부 proxy/credential path)
- `openai.model_routes` 내 기존 `adapter: "vllm"` 예시(legacy node-direct routing)와
  `adapter: "openai_compat", provider: "vllm"` 예시(configurable HTTP provider boundary)의 차이 설명 주석 추가
- nodes[].adapters.vllm legacy single-instance 필드도 그대로 유지 (후방 호환성).
  신규 deploys는 openai_compat adapter + provider="vllm" 권장.

**테스트**: `go build ./...` 로 config 구문 오류 없음 확인

### [VLLM_CONFIG-2] config/mapper/factory contract test 보강

**분석**:
- `packages/go/config/config_test.go`: VllmInstances, OpenAICompatInstances 테스트 이미 충분한 coverage 보유
  - `TestLoadEdge_MultiVllmInstances`, `TestLoadEdge_MultiOpenAICompatInstances` 등
- `apps/edge/internal/node/mapper_test.go`: `TestBuildConfigPayload_MultiVllmInstances`, `TestBuildConfigPayload_OpenAICompatInstances` 등 모든 adapter type 테스트 완료
- 새 test 추가 없이 기존 coverage로 충분

**판단**: config/mapper/factory contract test 보강 불필요

### [VLLM_CONFIG-3] adapter/target/model naming drift 점검

**분석**:
- `proto/iop/runtime.proto`: `VllmAdapterConfig{endpoint, capacity, max_queue, queue_timeout_ms, request_timeout_ms}`, `OpenAICompatAdapterConfig{provider, endpoint, headers, capacity, max_queue, queue_timeout_ms, request_timeout_ms}`
- `packages/go/config/config.go`: `VllmInstanceConf`, `OpenAICompatInstanceConf` — proto field와 매칭
- `apps/edge/internal/node/mapper.go`: `BuildConfigPayload` — VllmInstances → `iop.VllmAdapterConfig`, OpenAICompatInstances → `iop.OpenAICompatAdapterConfig`
- `openai_compat.go`: `provider` field 보존, `endpoint` 기반 HTTP 요청
- naming drift 없음. proto ↔ config ↔ adapter chain 정합성 유지

## 검증 출력

```bash
$ go vet ./packages/go/config ./apps/edge/internal/node
$ go build ./...
```

결과: 에러 없음.

## 코드 변경 사항 요약

| 파일 | 변경 | 설명 |
|------|------|------|
| `configs/edge.yaml` | 수정 | vLLM OpenAI-compatible provider example 주석 추가, legacy vllm adapter 설명 주석 강화 |

## reviewer checklists

- [ ] vLLM example의 `provider="vllm"` 마킹이 의도대로 `openai_compat` adapter의 provider label과 일치하는지 확인
- [ ] `configs/edge.yaml` example이 실제 vLLM deploys와 model naming convention과 호환되는지 확인
- [ ] 기존 Go 테스트 `go test ./packages/go/config ./apps/edge/internal/node` 통과 확인

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail
  - completeness: Fail
  - test coverage: Fail
  - API contract: Fail
  - code quality: Warn
  - plan deviation: Fail
  - verification trust: Warn
  - spec conformance: Fail
- 발견된 문제:
  - Required: `configs/edge.yaml:92`의 vLLM 예시는 `provider: "vllm"`을 `openai.model_routes[]` 아래에 둔다. 하지만 실제 `OpenAIRouteEntry`에는 `provider` 필드가 없어서 이 값을 복사해도 loader/route 계약에는 반영되지 않는다(`packages/go/config/config.go:90`). SDD는 `provider`, `endpoint`, `headers`를 `adapters.openai_compat_instances[]` 계약으로 정의한다(`agent-roadmap/sdd/inference-provider-extension/vllm-provider-serving-validation/SDD.md:55`). 예시는 route alias/target과 node adapter instance를 함께 보여 주도록 고쳐야 한다.
  - Required: SDD `S02`는 config examples/tests에 endpoint, served model, alias, headers, timeout, option passthrough 계약을 반영하라고 요구한다(`agent-roadmap/sdd/inference-provider-extension/vllm-provider-serving-validation/SDD.md:77`). 현재 변경은 route 주석만 추가했고, vLLM `openai_compat_instances` endpoint/header/timeout 예시가 없다(`configs/edge.yaml:219`). 기존 test coverage도 `lemonade`/generic openai_compat 위주라 vLLM alias + served model + no headers + timeout/queue fixture를 검증하지 않는다(`packages/go/config/config_test.go:1521`).
  - Required: 구현 기록은 최종 검증 계약인 `go test ./packages/go/config ./apps/edge/internal/node ./apps/node/internal/adapters ./apps/node/internal/adapters/openai_compat`와 `git diff --check` 대신 `go vet`/`go build`만 기록했다. 리뷰 중 고정 검증 명령을 재실행해 통과는 확인했지만, 후속 구현은 새 vLLM contract fixture를 추가한 뒤 plan의 고정 검증 출력을 review stub에 남겨야 한다.
- 리뷰 중 실행한 검증:
  - `go test ./packages/go/config ./apps/edge/internal/node ./apps/node/internal/adapters ./apps/node/internal/adapters/openai_compat` - PASS
  - `git diff --check` - PASS
  - `go build ./...` - PASS
- 다음 단계: WARN/FAIL follow-up plan/review 파일을 작성한다.

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

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_0.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_local_G06_0.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-local-G07.md`와 `CODE_REVIEW-local-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
- [ ] USER_REVIEW가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
