<!-- task=m-node-provider-first-config-surface/07_priority_routing plan=1 tag=REVIEW_API -->

# Plan - REVIEW_API

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

구현 완료 전에는 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용, 설계 결정, 검증 출력으로 채운다. 구현자는 아래 검증을 실행하고 active plan/review 파일은 그대로 둔 뒤 review 준비를 보고한다. 종결 처리, log rename, `complete.log` 작성, archive 이동은 code-review-skill 전용이다.

선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 막는 경우에만 review stub의 `사용자 리뷰 요청` 섹션에 연결 대상, 근거, 실행한 명령, 재개 조건을 기록하고 멈춘다. 구현 중 직접 사용자에게 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 환경/secret/service blocker, 일반 범위 조정, follow-up으로 닫을 수 있는 evidence 공백은 사용자 리뷰 요청이 아니다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/node-provider-first-config-surface.md`
- Task ids:
  - `priority-routing`: Provider-pool dispatch가 dispatch 가능한 후보 중 가장 낮은 `in_flight` provider를 우선하고, `in_flight`가 같은 후보에서만 낮은 숫자의 `priority`를 선택 기준으로 사용한다.
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Archived plan: `agent-task/m-node-provider-first-config-surface/07_priority_routing/plan_local_G06_0.log`
- Archived review: `agent-task/m-node-provider-first-config-surface/07_priority_routing/code_review_local_G06_0.log`
- Verdict: FAIL
- Required summary: `apps/edge/internal/service/model_queue_test.go:824`의 actual `resolveProviderPoolCandidates` 경로 테스트가 provider `Priority` 값을 설정하거나 `candidateNode.priority` 전달을 assert하지 않아, config `nodes[].providers[].priority`가 dispatch candidate까지 이어지는 증거가 빠져 있다.
- Affected files: `apps/edge/internal/service/model_queue_test.go`
- Prior verification evidence: `go test -count=1 ./packages/go/config ./apps/edge/internal/service ./apps/edge/internal/configrefresh` PASS, `go test -count=1 ./apps/edge/... ./packages/go/...` PASS.
- Roadmap carryover: SDD S08 / Milestone Task `priority-routing` completion evidence must include priority default/non-negative validation, `in_flight` selection, priority tie-break, equal priority rotation, and resolver priority propagation.
- Allowed narrow reread paths: `agent-task/m-node-provider-first-config-surface/07_priority_routing/plan_local_G06_0.log`, `agent-task/m-node-provider-first-config-surface/07_priority_routing/code_review_local_G06_0.log`.

## 배경

이 follow-up은 이전 리뷰의 Required 1건만 닫는다. 구현 코드는 이미 `resolveProviderPoolCandidates`에서 `priority: prov.Priority`를 설정하지만, 계획된 테스트 증거가 actual resolver 경로를 통하지 않고 hand-written `candidateNode`에 머물러 있다. SDD S08 PASS evidence로 쓰려면 config provider priority가 dispatch candidate까지 전달되는 테스트가 필요하다.

## 범위 결정 근거

- 포함: `apps/edge/internal/service/model_queue_test.go`의 resolver 테스트 보강.
- 제외: production code 변경, config schema/contract/refresh classification 변경, full-cycle runtime smoke. 이전 리뷰에서 production behavior와 Go regression은 PASS했고, 남은 문제는 누락된 planned test evidence다.
- 라우팅: `local-G03`. 범위가 단일 테스트 파일의 deterministic assertion 보강이며 local Go test로 검증 가능하다.

## 구현 체크리스트

- [ ] `resolveProviderPoolCandidates` actual 경로를 호출하는 service/model queue 테스트에 provider `Priority` fixture를 추가하고 반환된 `candidateNode.priority` 값을 assert한다.
- [ ] `go test -count=1 -run 'TestResolveProviderPoolCandidates' ./apps/edge/internal/service`와 `go test -count=1 ./packages/go/config ./apps/edge/internal/service ./apps/edge/internal/configrefresh`를 실행한다.
- [ ] `go test -count=1 ./apps/edge/... ./packages/go/...`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_API-1] Resolver Priority Propagation Test

문제:

- 이전 구현은 `apps/edge/internal/service/run_dispatch.go`에서 `priority: prov.Priority`를 설정하지만, actual resolver 테스트가 이 연결을 검증하지 않는다.
- `apps/edge/internal/service/model_queue_test.go`의 priority selection tests는 직접 만든 `candidateNode`를 사용하므로 config provider field -> resolver candidate field 연결 증거가 아니다.

해결 방법:

- `TestResolveProviderPoolCandidatesFiltersInvalidProviders` 또는 별도 focused test에서 `config.NodeProviderConf{Priority: <non-zero>}`를 가진 provider를 fixture로 둔다.
- `svc.resolveProviderPoolCandidates(...)` 결과에서 해당 provider의 `candidateNode.priority`가 fixture 값과 같은지 assert한다.
- 가능하면 explicit adapter provider와 provider-first adapter omitted provider 중 최소 하나에 대해 non-zero priority를 확인한다. 하나만 택한다면 기존 valid provider fixture에 붙여도 충분하다.

권장 예:

```go
Priority: 7,
...
if avail.priority != 7 {
	t.Errorf("prov-available priority: got %d, want 7", avail.priority)
}
```

테스트 작성:

- 파일: `apps/edge/internal/service/model_queue_test.go`
- 중간 검증: `go test -count=1 -run 'TestResolveProviderPoolCandidates' ./apps/edge/internal/service`
- 최종 검증:
  - `go test -count=1 ./packages/go/config ./apps/edge/internal/service ./apps/edge/internal/configrefresh`
  - `go test -count=1 ./apps/edge/... ./packages/go/...`
