# SDD User Review

## 상태

해결됨

## 검토 대상

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/provider-catalog-device-status/SDD.md`
- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/provider-catalog-device-status.md`

## 사용자 결정 항목

### [D01] Pool 계약 위치

- 결정 필요: model catalog와 provider pool을 Edge config에서 어떤 최소 구조로 표현할지 결정한다.
- 결정: `model_catalogs`나 `model_pools` 같은 별도 이름 대신 `models[]`를 사용한다. `models[].id`는 `qwen3.6:35b` 같은 외부 OpenAI-compatible model key이자 운영 catalog model id다. 단일 provider만 쓰는 model도 같은 구조로 정의하고, `providers`에 provider id 하나만 둔다. IOP는 `models[]`에 정의된 model만 새 provider-pool 경로에서 사용한다.
- 결정: `models[].providers`는 provider id를 key로, 해당 provider에서 실제 호출할 model name을 value로 둔다. provider 자체는 `nodes[].providers[]` 아래에 정의한다. 같은 Node 아래에 여러 provider가 있을 수 있고, 각 provider는 제공 가능한 실제 model name을 `models[]` list로 가진다.
- 결정: `models[].providers`의 key는 반드시 `nodes[].providers[].id`와 매칭되어야 하고, value는 해당 provider의 `models[]` list 안에 있어야 한다.
- 추천안: 승인됨. `models[]`가 model catalog와 외부 model key 목록을 동시에 담당하고, provider 매핑은 `providers: <provider-id>: <served-model-name>` 형태로 둔다.
- 대안: 없음. 기존 `openai.model_routes[]` 확장이나 별도 `model_pools[]` 분리는 D01 범위에서 채택하지 않는다.
- 영향: 외부 호출 모델명, 운영 model catalog, provider candidate 매핑이 한 구조에 고정된다. provider 상세 정의와 provider별 model list는 Node 하위 provider 계약으로 이어진다.
- 적용 위치:
  - SDD: `Interface Contract`, `Acceptance Scenarios S01/S05`
  - Milestone: `alias-contract`, `pool-compat`, `구현 잠금`

### [D02] Candidate 선택 정책

- 결정 필요: provider candidate 선택 기준을 capacity/in-flight 중심으로 시작할지, priority/weight/fallback 정책까지 MVP에 포함할지 결정한다.
- 결정: MVP는 available provider 중 `in_flight / capacity` load ratio가 가장 낮은 후보를 우선 선택한다. 단순히 남은 slot이 있다는 이유로 더 높은 load ratio의 provider를 선택하지 않는다. 예를 들어 2/3 provider와 1/3 provider가 있으면 1/3 provider를 우선한다.
- 결정: capacity가 0이거나 알 수 없으면 selection 대상에서 제외하거나 unavailable로 본다. 동률이면 deterministic tie-break를 사용한다.
- 결정: priority, weight, fallback policy는 MVP 필수 필드로 넣지 않고 후속 확장으로 둔다.
- 추천안: 승인됨. health/available 여부를 먼저 보고, 그 다음 `in_flight / capacity` load ratio 기준으로 선택한다.
- 대안: priority/weight/fallback을 MVP에 포함한다.
- 영향: scheduler가 단순 여유 slot 기준보다 균등한 load distribution을 우선하게 된다. policy field를 아직 도입하지 않으므로 config 복잡도는 낮게 유지된다.
- 적용 위치:
  - SDD: `State Machine`, `Acceptance Scenarios S04`
  - Milestone: `selection-policy`, `구현 잠금`

### [D03] Target rewrite 책임

- 결정 필요: provider마다 실제 served target이 다를 때 Edge가 target rewrite를 담당할지, Node adapter instance가 alias mapping을 담당할지 결정한다.
- 결정: target rewrite와 routing/control 책임은 모두 Edge가 가진다. Edge가 provider를 선택한 뒤 `models[].providers[provider_id]` 값을 concrete served target으로 해석해 Node에 전달한다.
- 결정: Node/provider adapter는 catalog model id나 alias를 provider별 served model name으로 자체 rewrite하지 않는다. Node는 Edge가 지정한 provider와 concrete target을 실행한다.
- 추천안: 승인됨. Edge-owned control 원칙으로 고정한다.
- 대안: 없음. Node adapter instance alias mapping은 채택하지 않는다.
- 영향: queue, provider selection, target rewrite, 관측/debug 책임이 Edge에 모인다. Node는 실행자 역할로 단순화된다.
- 적용 위치:
  - SDD: `Interface Contract`, `Acceptance Scenarios S03`
  - Milestone: `target-rewrite`, `구현 잠금`

### [D04] Catalog/status 표시 범위

- 결정 필요: provider category를 API, CLI, local inference 외에 어디까지 포함하고, local device/provider 상태를 health, capacity, model list, queue, runtime process 중 어디까지 추적할지 결정한다.
- 결정: MVP provider category는 `api`, `cli`, `local_inference`로 시작한다.
- 결정: MVP 상태 추적은 `health`, `capacity`, `in_flight`, derived `load_ratio`, `models`, `queued`까지 포함한다.
- 결정: runtime process/container detail과 CPU/GPU/RAM/VRAM resource telemetry는 MVP 필수 범위에서 제외하고 후속으로 둔다.
- 추천안: 승인됨. D02 selection에 필요한 필드와 catalog 관측에 필요한 최소 상태만 포함한다.
- 대안: runtime process, container/process lifecycle, 상세 resource telemetry까지 MVP에 포함한다.
- 영향: Control Plane/Client/CLI가 provider 사용 가능 여부와 부하 상태를 볼 수 있고, 상세 host/process/resource 관측은 후속으로 분리된다.
- 적용 위치:
  - SDD: `Source of Truth`, `Interface Contract`, `Acceptance Scenarios S06/S07`
  - Milestone: `category-map`, `device-status`, `구현 잠금`

### [D05] Lifecycle capability 표시 방식

- 결정 필요: Ollama/Lemonade처럼 모델 lifecycle API가 있는 provider와 vLLM/SGLang처럼 process/container lifecycle 중심인 provider를 catalog에서 어떻게 구분할지 결정한다.
- 결정: MVP catalog에는 provider별 lifecycle capability를 coarse flags로만 표시한다. 예: `list_models`, `load_model`, `unload_model`, `pull_model`, `delete_model`.
- 결정: 상세 lifecycle 동작, compatibility, benchmark, quality, model별 qualification 결과는 후속 Qualification Report Milestone으로 넘긴다.
- 추천안: 승인됨. catalog는 capability 차이를 볼 수 있는 정도로만 표시하고, 검증/품질/호환성 판단은 후속 리포트로 분리한다.
- 대안: lifecycle API 세부 동작과 제어 가능 여부를 catalog MVP에 직접 포함한다.
- 영향: catalog는 provider capability 비교 표면으로 유지되고, lifecycle 관리/검증/품질 판단 책임은 후속 Milestone으로 분리된다.
- 적용 위치:
  - SDD: `Interface Contract`, `Acceptance Scenarios S08`
  - Milestone: `lifecycle-cap`, `구현 잠금`

### [D06] 운영 표면 제어 포함 여부

- 결정 필요: provider pool과 catalog를 읽기 전용 관찰로 시작할지, enable/disable 같은 제어까지 포함할지 결정한다.
- 결정: MVP는 읽기 전용 관찰과 Edge config 기반 routing 계약까지만 포함한다.
- 결정: enable/disable, drain, fallback 우선순위 변경, capacity override 같은 runtime 제어는 후속 Milestone으로 둔다.
- 추천안: 승인됨. provider catalog/pool MVP는 관찰 표면과 routing 계약을 확정하고, runtime 제어는 권한/audit/실패 처리와 함께 후속으로 분리한다.
- 대안: enable/disable, drain, fallback 우선순위 변경 같은 제어를 MVP에 포함한다.
- 영향: MVP의 권한, audit, failure handling 부담이 낮아지고, Control Plane/Client/CLI runtime control 책임은 후속 Milestone에서 별도로 설계한다.
- 적용 위치:
  - SDD: `문제 / 비목표`, `Acceptance Scenarios S09/S10`
  - Milestone: `boundary`, `ops-review`, `구현 잠금`

## 승인 항목

- [x] 위 결정 항목을 승인했다.
- [x] SDD 잠금 해제를 승인했다.

## 답변 기록

- D01: 사용자는 `model_catalogs`/`model_pools` 대신 `models[]`를 사용하고, 단일 provider model도 같은 구조로 정의하며, `models[].providers`를 provider id -> served model name map으로 두는 방향을 확정했다. provider 정의는 `nodes[].providers[]` 아래에 두고, 각 provider는 제공 가능한 실제 model name을 `models[]` list로 가진다. `models[].providers`의 key는 provider id와 매칭되고, value는 해당 provider의 `models[]` 안에 있어야 한다.
- D02: 사용자는 provider 선택 기준을 단순 remaining slot이 아니라 `in_flight / capacity` load ratio로 확정했다. available 후보 중 load ratio가 가장 낮은 provider를 우선하며, 2/3과 1/3이 있으면 1/3을 선택한다. priority/weight/fallback은 MVP 필수 필드에서 제외하고 후속 확장으로 둔다.
- D03: 사용자는 routing/control 책임은 Edge가 가져야 한다는 설계 원칙을 확정했다. Edge가 provider 선택과 target rewrite를 수행하고, Node/provider adapter는 Edge가 전달한 concrete target을 실행한다.
- D04: 사용자는 MVP provider category를 `api`, `cli`, `local_inference`로 확정했다. 상태 추적은 `health`, `capacity`, `in_flight`, derived `load_ratio`, `models`, `queued`까지 포함하고, runtime process/container detail과 CPU/GPU/RAM/VRAM resource telemetry는 후속으로 둔다.
- D05: 사용자는 MVP catalog에 provider별 lifecycle capability를 coarse flags로만 표시하고, 상세 lifecycle 동작, compatibility, benchmark, quality, model별 qualification 결과는 후속 Qualification Report Milestone으로 넘기는 방향을 확정했다.
- D06: 사용자는 MVP를 읽기 전용 관찰과 Edge config 기반 routing 계약까지만 포함하고, enable/disable, drain, fallback 우선순위 변경, capacity override 같은 runtime 제어는 후속 Milestone으로 두는 방향을 확정했다.

## 해결 조건

- 모든 사용자 결정 항목의 답변이 SDD에 반영되어 있다.
- `USER_REVIEW.md`가 `user_review_N.log`로 이동되어 있다.
- 남은 잠금 항목이 없으면 SDD 상태가 `[승인됨]`이고 `SDD 잠금` 상태가 `해제`다.
