# SDD: vLLM provider 서빙 경로 추가

## 위치

- Milestone: `agent-roadmap/phase/inference-provider-extension/milestones/vllm-provider-serving-validation.md`
- Phase: `agent-roadmap/phase/inference-provider-extension/PHASE.md`

## 상태

[승인됨]

## SDD 잠금

- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
  - 없음

## 문제 / 비목표

- 문제: vLLM provider 작업은 DGX Spark field host의 container 준비, OpenAI-compatible provider 설정 계약, Edge/Node 모델 조회와 chat 경로, streaming SSE, split-host smoke가 함께 얽혀 있다. 구현 전에 provider 경계와 검증 증거 기준을 하나의 source of truth로 고정해야 한다.
- 비목표:
  - provider/device/model qualification report 저장/조회/비교 제품화
  - cloud fallback, 자동 부하 라우팅, 품질 평가 feedback 계층 구현
  - Responses API 세부 호환 구현
  - vLLM 서버 배포/운영 자체의 제품화
  - 기존 Ollama 경로 완료 기록 재작성

## Source of Truth

| 영역 | 기준 | 메모 |
|------|------|------|
| Roadmap | `agent-roadmap/phase/inference-provider-extension/milestones/vllm-provider-serving-validation.md` | 기능 Task 상태와 완료 근거 원장 |
| Contract | `agent-contract/provided/openai-compatible-api.md` | OpenAI-compatible 입력 표면과 내부 `adapter + target` 경계 |
| Code | `apps/edge`, `apps/node`, `packages/go/config`, `proto/iop`, `configs`, `scripts` | Edge route, Node adapter, config contract, smoke 구현 기준 |
| Test Rules | `agent-test/local/rules.md`, `agent-test/local/edge-smoke.md`, `agent-test/local/node-smoke.md`, `agent-test/local/platform-common-smoke.md` | local/field 검증 경계와 DGX Spark 접근 기준 |
| External Provider | vLLM OpenAI-compatible server, `nvidia/Qwen3.6-35B-A3B-NVFP4` | DGX Spark ARM64/Blackwell field validation 기준 model |
| User Decision | 없음 | 현재 Milestone에 남은 사용자 전용 결정 없음 |

## State Machine

| 상태 | 진입 조건 | 다음 상태 | 근거 |
|------|-----------|-----------|------|
| `planned` | SDD 승인 및 잠금 해제 | `container-ready` | `spark-container` plan PASS |
| `container-ready` | DGX Spark vLLM container가 `/v1/models`에 응답 | `config-contract-ready` | image/tag/cache/launch/health evidence |
| `config-contract-ready` | vLLM endpoint, served model, alias, auth/header, timeout, option passthrough 계약 반영 | `edge-node-validated` | config/tests/smoke evidence |
| `edge-node-validated` | `/v1/models`, non-streaming chat, streaming SSE가 vLLM provider 경로로 수렴 | `field-smoke-ready` | Edge/Node smoke evidence |
| `field-smoke-ready` | split-host smoke에서 vLLM target/model 왕복 검증 | `complete-candidate` | field smoke evidence |
| `complete-candidate` | 모든 기능 Task PASS 증거가 complete.log에 남음 | Milestone 완료 후보 | update-roadmap |

## Interface Contract

- 계약 원문: `agent-contract/provided/openai-compatible-api.md`
- 입력:
  - `openai.model`: 외부 OpenAI-compatible API에 노출되는 alias. DGX Spark vLLM 기준값은 `qwen3.6:35b`.
  - `openai.model_routes[].adapter`: 내부 provider adapter 이름. vLLM은 OpenAI-compatible inference server 공통 adapter 계열로 다룬다.
  - `openai.model_routes[].target`: provider가 실제로 호출할 served model. DGX Spark vLLM 기준값은 `nvidia/Qwen3.6-35B-A3B-NVFP4`.
  - `adapters.openai_compat_instances[].provider`: provider profile 식별자. vLLM 경로는 `vllm`을 사용한다.
  - `adapters.openai_compat_instances[].endpoint`: OpenAI-compatible server base URL. field 기준은 `http://<DGX_SPARK_HOST>:8000/v1`이며 실제 host 값은 tracked 문서에 고정하지 않는다.
  - `adapters.openai_compat_instances[].headers`: 인증/추가 header. field smoke 기본값은 없음이다.
  - `options`, `format`, `tools`, `think`, `keep_alive`: adapter-owned `model`/`stream`을 침범하지 않는 범위에서 provider 요청으로 passthrough한다.
- 출력:
  - `/v1/models`: Edge는 route alias를 노출하고, provider health check는 served model이 조회되는지 확인한다.
  - `/v1/chat/completions`: non-streaming 응답이 OpenAI-compatible chat response로 반환된다.
  - streaming `/v1/chat/completions`: SSE chunk, content/reasoning delta, `finish_reason`, 종료 신호가 Edge/Node 경로를 지나 안정적으로 전달된다.
- 금지:
  - 내부 실행 계약을 model-centered 구조로 되돌리지 않는다.
  - tracked 문서/설정에 private endpoint, token, secret을 기록하지 않는다.
  - 현재 작업 container 안에서 DGX Spark vLLM container를 기동하지 않는다.
  - Edge가 Node provider 경로를 우회해 vLLM endpoint를 직접 호출하지 않는다.

## Acceptance Scenarios

| ID | Milestone Task | Given | When | Then |
|----|----------------|-------|------|------|
| S01 | `spark-container` | DGX Spark field host 접근과 vLLM model 기준이 정해져 있다 | ARM64/Blackwell용 vLLM container image/tag, cache volume, launch command를 적용한다 | field host의 provider `/v1/models`가 응답하고 image digest/tag와 launch evidence가 남는다 |
| S02 | `config-contract` | vLLM provider를 OpenAI-compatible 공통 adapter 계열로 쓰기로 했다 | config/examples/tests에 endpoint, served model, alias, headers, timeout, option passthrough 계약을 반영한다 | Edge/Node/config 계약이 `adapter + target` 기준으로 검증된다 |
| S03 | `models-chat` | vLLM config contract가 반영되어 있다 | Edge `/v1/models`와 non-streaming `/v1/chat/completions` smoke를 실행한다 | route alias 조회와 chat 왕복이 vLLM provider 경로로 검증된다 |
| S04 | `streaming` | vLLM provider endpoint가 streaming을 지원한다 | streaming `/v1/chat/completions` smoke를 실행한다 | SSE chunk, finish reason, 종료 신호가 검증된다 |
| S05 | `field-smoke` | container, config, local smoke 기준이 준비되어 있다 | split-host field smoke에서 vLLM target/model을 선택한다 | 실제 Edge/Node field 경로에서 모델 조회와 chat 왕복이 검증된다 |
| S06 | `follow-up-scope` | code/config/script 변경이 필요한 항목이 식별되어 있다 | Milestone task group에 후속 plan을 작성한다 | 구현 범위가 active plan으로 분리되어 있다 |

## Evidence Map

| Scenario | Required Evidence | `agent-task` 연결 | `Spec Completion` 기대 |
|----------|-------------------|------------------|---------------------------|
| S01 | DGX Spark `docker image inspect`, launch command, health check `/v1/models` output | `agent-task/m-vllm-provider-serving-validation/01_spark_container` | vLLM container image/tag/cache/launch/health 기준 검증 |
| S02 | config examples/tests, mapper/factory/config test output | `agent-task/m-vllm-provider-serving-validation/02+01_config_contract` | vLLM endpoint/served model/alias/auth/timeout/options 계약 검증 |
| S03 | fake 또는 real vLLM smoke의 `/v1/models`와 non-streaming chat output | `agent-task/m-vllm-provider-serving-validation/03+02_openai_vllm_smoke` | Edge `/v1/models`와 non-streaming chat provider 수렴 검증 |
| S04 | streaming smoke SSE chunk, `finish_reason`, `data: [DONE]` output | `agent-task/m-vllm-provider-serving-validation/03+02_openai_vllm_smoke` | streaming chat completion 전달 검증 |
| S05 | split-host field smoke command/output와 target/model evidence | `agent-task/m-vllm-provider-serving-validation/04+03_field_smoke` | 실제 field 경로 모델 조회와 chat 왕복 검증 |
| S06 | active plan/review stub 목록과 Milestone `follow-up-scope` 체크 | `agent-task/m-vllm-provider-serving-validation/*` | 코드 수정 범위가 후속 plan으로 정리됨 |

## Cross-repo Dependencies

- 없음

## Drift Check

- [x] Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- [x] Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
- [x] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- [x] 사용자 리뷰가 필요한 항목은 `USER_REVIEW.md`에만 남겼다.

## 사용자 리뷰 이력

- 없음

## 작업 컨텍스트

- 표준선: 내부 실행 계약은 `adapter + target`을 유지하고, OpenAI-compatible API는 외부 호환 입력 표면으로 둔다.
- 표준선: vLLM은 전용 내부 adapter 확장보다 OpenAI-compatible inference server 공통 adapter 계열의 `provider: vllm` profile과 target/model 매핑으로 다룬다.
- 표준선: DGX Spark field host 값과 private endpoint는 `agent-test/local/rules.md`에만 둔다.
- field container 후보: ARM64 환경은 vLLM OpenAI-compatible server Docker image의 ARM64 tag를 우선 검증하고, 실제 digest/tag는 `01_spark_container` 완료 evidence로 고정한다.
- 후속 SDD: 없음
