<!-- task=m-model-group-long-context-admission/03+02_queue_skip plan=0 tag=QUEUE_SKIP -->

# Code Review Reference - QUEUE_SKIP

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is mandatory.** Complete implementation-owned sections, paste actual verification output, then stop with active files in place. Do not ask the user directly and do not run review finalization.

## 개요

date=2026-07-05
task=m-model-group-long-context-admission/03+02_queue_skip, plan=0, tag=QUEUE_SKIP

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/model-group-long-context-admission.md`
- Task ids:
  - `queue-skip`: long queue head가 long slot을 기다릴 때 뒤의 normal 요청이 빈 일반 capacity로 dispatch
- Completion mode: check-on-pass

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

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

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [QUEUE_SKIP-1] Dispatchable queue item scan | [x] |

## 구현 체크리스트

- [x] queue pump가 head item만 보지 않고 앞에서부터 dispatch 가능한 item을 찾아 선택하도록 바꾼다.
- [x] long slot 부족으로 막힌 long item은 queue에 남기고, 뒤의 normal item은 일반 capacity가 있으면 dispatch한다. 검증: long head 대기 중 normal 요청이 head-of-line blocking 없이 완료된다. (`TestQueueSkipsLongHeadWhenNormalBehindCanDispatch` PASS)
- [x] 같은 class/같은 dispatch 가능 조건에서는 기존 FIFO와 priority/capacity tie-breaker를 유지한다. (front-scan이 최소 index의 dispatchable item을 먼저 선택; `TestQueueSkipPreservesFIFOAmongDispatchableNormalItems`, `TestModelQueueFIFOOrdering` PASS)
- [x] timeout, cancel, queue length accounting이 scan/pop 방식에서도 깨지지 않게 regression tests를 유지/추가한다. (기존 timeout/cancel/overflow/terminal-release 테스트 전부 PASS)
- [x] `go test -count=1 ./apps/edge/internal/service`를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

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

- [x] 판정을 append한다.
- [x] active review/plan을 `code_review_local_G07_0.log`, `plan_local_G07_0.log`로 아카이브한다.
- [x] PASS이면 `complete.log` 작성 후 archive로 이동한다.
- [ ] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.

## 계획 대비 변경 사항

- 계획의 예상 구조는 `group.findDispatchableLocked` 같은 별도 helper 추출을 시사했으나, 기존 `findAvailableNodeLocked`가 이미 (long gate 포함) dispatch 가능 여부 평가를 담당하고 있어 별도 scan helper를 추가하지 않고 유일한 pump 지점인 `tryDispatchLocked` 하나만 front-scan 루프로 교체했다. 심볼 추가/이름 변경 없음. 최소 변경으로 head-of-line blocking을 제거하고 회귀 표면을 줄이기 위함이다.
- `model_queue.go`만 수정하면 충분해 계획의 후보였던 `service_test.go` 추가는 하지 않았다. `admit` 초기 dispatch 경로는 이미 `findAvailableNodeLocked`로 임의의 dispatchable candidate를 즉시 선택하므로 head-of-line blocking은 slot release 후 재펌프(`tryDispatchLocked`)에서만 발생했고, unit 레벨에서 결정적으로 재현 가능해 추가 integration 테스트가 불필요했다.

## 주요 설계 결정

- `tryDispatchLocked`를 "head-only, 1건 dispatch 후 return"에서 "front-scan, 진행이 있으면 재스캔"으로 변경했다. 각 outer pass에서 앞에서부터 첫 dispatchable item을 pop해 dispatch하고, item 제거(dispatch 또는 timeout)가 있으면 처음부터 다시 스캔한다. queue 길이가 유한하고 progress가 있을 때만 반복하므로 종료가 보장된다.
- long slot full로 막힌 long head는 `findAvailableNodeLocked(long=true)`에서 후보 없음으로 평가되어 스킵되고 queue에 남는다. 뒤의 normal item은 `long=false`로 평가되어 long slot state를 보지 않고 일반 capacity만으로 dispatch된다 (SDD D05/D06).
- 기존 동작(단일 slot release 시 1건 dispatch)은 그대로 유지된다. front-scan은 여러 slot이 동시에 열린 경우(예: `releaseNode`)에 dispatchable item을 모두 소진하도록 더 정확해졌으나, capacity 검사가 그대로 살아 있어 over-dispatch는 없다.
- FIFO/priority/rotation은 `findAvailableNodeLocked`와 최소 index 우선 선택으로 보존된다.

## 사용자 리뷰 요청

_기본값은 `없음`이다. 구현 중 새 결정이 필요해 보여도 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 이 섹션은 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채운다. 외부 환경/secret/서비스 준비, 검증 증거 공백, 반복 실패, 일반 범위 조정은 사용자 리뷰 요청이 아니며 `검증 결과`, `계획 대비 변경 사항`, 또는 code-review의 일반 follow-up plan으로 처리한다._

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

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

- long head blocked 상태에서 normal이 dispatch되고 long이 queue에 남는지 확인한다.
- FIFO/priority/cancel/timeout 회귀가 없는지 확인한다.
- normal 후보 평가에서 long slot state를 사용하지 않는지 확인한다.

## 검증 결과

### QUEUE_SKIP-1 중간 검증

```bash
$ go test -count=1 -run 'TestQueueSkip' -v ./apps/edge/internal/service
=== RUN   TestQueueSkipsLongHeadWhenNormalBehindCanDispatch
--- PASS: TestQueueSkipsLongHeadWhenNormalBehindCanDispatch (0.00s)
=== RUN   TestQueueSkipPreservesFIFOAmongDispatchableNormalItems
--- PASS: TestQueueSkipPreservesFIFOAmongDispatchableNormalItems (0.00s)
PASS
ok  	iop/apps/edge/internal/service	0.004s
```

### 최종 검증

```bash
$ go test -count=1 ./apps/edge/internal/service
ok  	iop/apps/edge/internal/service	0.461s

$ gofmt -l apps/edge/internal/service/model_queue.go apps/edge/internal/service/model_queue_test.go
(output 없음)

$ go build ./...
(output 없음)
```

기대 결과 PASS 충족. 신규 테스트 2개 + 기존 FIFO/timeout/cancel/overflow/terminal-release/long-slot 회귀 테스트 모두 통과.

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Fill every implementation-owned section before saving.**

## 코드리뷰 결과

- 종합 판정: PASS
- 차원별 평가:
  - correctness: Pass
  - completeness: Pass
  - test coverage: Pass
  - API contract: Pass
  - code quality: Pass
  - implementation deviation: Pass
  - verification trust: Pass
  - spec conformance: Pass
- 발견된 문제: 없음
- 리뷰 근거:
  - `tryDispatchLocked`가 queue 앞에서부터 첫 dispatchable item을 찾아 pop/dispatch하며, long slot full인 long head는 queue에 남기고 뒤 normal item은 일반 capacity 기준으로 dispatch한다.
  - `findAvailableNodeLocked`의 long gate가 `long == true`일 때만 적용되어 SDD D05/D06과 S06을 충족한다.
  - 신규 `TestQueueSkipsLongHeadWhenNormalBehindCanDispatch`와 `TestQueueSkipPreservesFIFOAmongDispatchableNormalItems`가 S06 및 FIFO 회귀를 직접 검증한다.
- 리뷰어 검증:
  - `gofmt -l apps/edge/internal/service/model_queue.go apps/edge/internal/service/model_queue_test.go` -> 출력 없음
  - `go test -count=1 -run 'TestQueueSkip|TestModelQueueFIFOOrdering|TestModelQueueLongDispatchReservesBothCounters|TestModelQueueNormalRequestDoesNotReserveLongSlot' -v ./apps/edge/internal/service` -> PASS
  - `go test -count=1 ./apps/edge/internal/service` -> PASS
  - `go build ./...` -> PASS
  - `go test -count=1 ./apps/edge/...` -> PASS
  - `git diff --check` -> PASS
- 다음 단계: PASS이므로 `complete.log` 작성 후 task directory를 archive로 이동한다. `m-model-group-long-context-admission` completion metadata를 보고하며 roadmap 수정은 런타임 책임으로 남긴다.
