<!-- task=m-model-group-long-context-admission/06+01,02,03,04,05_capacity_smoke plan=0 tag=CAPACITY_SMOKE -->

# Code Review Reference - CAPACITY_SMOKE

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is mandatory.** Record preflight, smoke stdout/stderr, and status snapshot paths. External environment blockers are verification blockers, not user-review requests unless a selected Milestone lock decision is unresolved.

## 개요

date=2026-07-05
task=m-model-group-long-context-admission/06+01,02,03,04,05_capacity_smoke, plan=0, tag=CAPACITY_SMOKE

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/model-group-long-context-admission.md`
- Task ids:
  - `capacity-smoke`: dev 환경 normal 10-way, mixed long/normal, all-long-slot-full queue 시나리오와 최종 회복 근거
- Completion mode: check-on-pass

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

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

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [CAPACITY_SMOKE-1] Long-context admission dev smoke | [x] script/doc 구현·검증 완료. dev 재배포 + 배포 config 보정 후 3 시나리오 라이브 S09 증거 수집 완료 (아래 검증 결과 참조) |

## 구현 체크리스트

- [x] dev smoke profile/script를 추가하거나 기존 dev edge smoke에 long-context admission scenarios를 확장한다. — `scripts/e2e-long-context-admission-smoke.sh` 신규, `agent-test/dev/long-context-admission-smoke.md` 신규, `agent-test/dev/edge-smoke.md` 교차링크.
- [x] preflight가 source state, config check, endpoint reachability, provider identities, current provider snapshots를 기록하게 한다. — runner preflight PASS(3 provider healthy, capacity 2/4/3=9).
- [x] normal 10-way scenario를 실행하고 총 `in_flight=9`, `queued>=1` 관측 후 완료 시 `in_flight=0`, `queued=0` 회복을 저장한다. — peak `in_flight=9`, `queued=3`, http_200=10/10, 회복 `in_flight=0`/`queued=0`. `long_in_flight`은 Control Plane status view 미노출로 `n/a`.
- [x] mixed long/normal scenario를 실행해 long slot full 중 normal이 head-of-line blocking 없이 완료되는 evidence를 저장한다. — post-fix: normal http_200=6/6, mid-run에서 long 4개가 long slot 정확 점유(mac=1/1, gx10=1/1, onex=2/2)하는 동안 normal 완료, 회복 0/0.
- [x] all-long-slot-full scenario를 실행해 long requests가 queue 대기 후 slot 회복 시 dispatch되고 최종 counters가 0으로 회복되는 evidence를 저장한다. — post-fix: peak `in_flight=4`(long slot total로 캡), `queued` 발생, Edge 로그 `queue_reason=long_context_capacity_full` 2건, long http_200=6/6, 회복 0/0.
- [x] smoke stdout/stderr와 status snapshot 파일 경로를 review stub에 기록한다. — 아래 검증 결과에 명령·출력·경로 기록.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

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

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

## 계획 대비 변경 사항

- 계획의 `/v1/responses` + `/v1/chat/completions` 이중 endpoint 대신 `/v1/chat/completions`만 구동했다. 두 경로는 동일 provider-pool admission으로 수렴하고, 라이브 부하를 줄이기 위해 chat 경로로 통일했다.
- status 폴링을 고정 시간창(초기 90s)에서 요청 완료 기반(`<label>.polling_done` 플래그, POLL_SECS는 안전 상한 3600s)으로 바꿨다. long-context 요청이 느려 고정 창으로는 peak을 놓치기 때문이다.
- 스크립트를 repo가 아닌 위치(runner `/tmp`)에서 실행할 수 있도록 `IOP_LONG_SMOKE_REPO`로 `config check` 기준 repo 경로를 override 가능하게 했다.
- long prompt는 기본 720000 chars(~225k tokens)이나 라이브 실행에서는 `IOP_LONG_SMOKE_LONG_CHARS=384000`(~120k tokens, threshold 초과)로 override해 부하를 낮췄다. estimator는 `runes*5/16` 근사다.
- 계획 범위 밖이었으나, 라이브 S09 증거 수집이 (1) 배포 stale, (2) 배포 config의 long_context_capacity 누락으로 막혀 사용자 승인 후 dev Edge 재배포 + 배포 config 보정을 수행했다. 상세는 `검증 결과`의 재배포 절차/config gap 섹션 참조.
- `long_context_threshold_tokens`를 사용자 결정에 따라 `30000`으로 배포 dev config에 설정했다(기본 100000). tracked 기본값/SDD 반영은 follow-up으로 분리.

## 주요 설계 결정

- 라이브 실행은 로컬 host에서 dev Edge/Control Plane 포트에 직접 도달하지 못해(방화벽) `ssh toki@toki-labs.com` runner에서 실행했다. base_url/status_url은 runner-local(`127.0.0.1:18083`, `127.0.0.1:18001`)로 지정했다.
- bearer token(`<masked-dev-token>`, 저민감도 로컬 dev 토큰)은 runner config에서 env로 소싱하고 명령/로그/tracked 파일에 원문을 남기지 않았다.
- 시나리오는 pool이 idle(`in_flight=0`)로 회복된 상태에서만 다음 시나리오를 시작하도록 순차 실행했다.
- Control Plane HTTP status view가 long 필드를 노출하지 않으므로, 스크립트는 status JSON에 long 필드가 있으면 자동 사용하고 없으면 `n/a` 처리 후 Edge log 기반 확인을 안내하도록 forward-compatible하게 작성했다.

## 사용자 리뷰 요청

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

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

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

- smoke가 normal 10-way, mixed, all-long-slot-full 세 시나리오를 모두 (재배포·config 보정 후) 라이브 실행했는지 확인한다.
- 최종 snapshot마다 `in_flight=0`, `queued=0` 회복 근거가 있는지 확인한다. `long_in_flight`은 Control Plane status view 미노출(follow-up #1)이므로 Edge 로그 `queue_reason`/`context_class`로 long-slot 예약·대기·회복을 확인한다.
- all-long-slot-full의 long slot 게이팅 증거로 Edge 로그 `queue_reason="long_context_capacity_full"`와 peak `in_flight`가 long slot total(4)로 캡되었는지 확인한다.
- 배포 stale/config gap이 재배포·config 보정으로 해소되었고, threshold 정책·status view 확장이 follow-up으로 남았는지 확인한다.

## 검증 결과

### 로컬 정적 검증 (local checkout, HEAD=2d08d240d48a954df6847df2ba08fb8b39fc3f7d)

```bash
$ git rev-parse HEAD
2d08d240d48a954df6847df2ba08fb8b39fc3f7d
$ git status --short
 M agent-test/dev/edge-smoke.md
?? agent-test/dev/long-context-admission-smoke.md
?? scripts/e2e-long-context-admission-smoke.sh
$ go run ./apps/edge/cmd/edge config check --config configs/edge.yaml
OK configs/edge.yaml
$ bash -n scripts/e2e-long-context-admission-smoke.sh
(no output; syntax OK)
$ bash scripts/e2e-long-context-admission-smoke.sh --preflight --config configs/edge.yaml --out-dir /tmp/iop-long-admission-smoke
# 로컬 host에서 dev 포트 미도달(방화벽) → preflight rc=3, BLOCKER로 정확한 실패 명령 기록:
#   curl -fsS --connect-timeout 10 http://toki-labs.com:18083/v1/models
#   curl -fsS --connect-timeout 10 http://127.0.0.1:18001/edges/edge-toki-labs-dev/status
```

### 초기 라이브 검증 (재배포 전 / 배포 stale — 아래 post-fix로 대체됨)

runner `ssh toki@toki-labs.com`, base=127.0.0.1:18083, status=127.0.0.1:18001. 이 시점 runner checkout HEAD=`59e55d409ebaa978d0ee80920ef7c4c30c0f09ce`, 배포 edge 바이너리 빌드 2026-07-05 04:38, 실행 04:40 (long-admission 미배포).

```text
$ ... --preflight --config build/dev-runtime/edge.yaml
config check: OK build/dev-runtime/edge.yaml
/models OK -> model=qwen3.6:35b
status OK: mac-mlx-vllm cap=2 in_flight=0 / gx10-vllm cap=4 in_flight=0 / onexplayer-lemonade cap=3 in_flight=0 (모두 healthy)
provider present: gx10-vllm, onexplayer-lemonade, mac-mlx-vllm
NOTE: status view가 long_in_flight/long_queued 미노출
PREFLIGHT OK (rc=0)

$ ... --scenario normal-10
peak_in_flight=9  peak_queued=3   normal http_200=10/10
final: in_flight=0 queued=0 (recovery OK)

$ ... --scenario mixed   (IOP_LONG_SMOKE_LONG_CHARS=384000)
peak_in_flight=4  peak_queued=0   normal http_200=6/6  (head-of-line blocking 없음)
final: in_flight=0 queued=0 (recovery OK)

$ ... --scenario all-long-slot-full   (IOP_LONG_SMOKE_LONG_CHARS=384000)
peak_in_flight=6  peak_queued=0   long http_200=5/6
final: in_flight=0 queued=0 (recovery OK)
mid-run 관측: in_flight=6 (mac=2/2, gx10=2/4, onexplayer=2/3), queued=0
```

evidence 파일 경로(runner): `/tmp/iop-long-admission-smoke/` 아래 `preflight_*`, `*_peaks_*.txt`, `*_final_*.json`, `*.code`, `*.resp.json`.

### 초기 blocker(배포 stale) — 재배포로 해소됨

- 최초 라이브 실행 시 배포 dev Edge 바이너리는 runner checkout `59e55d4`("openai-compatible tool call boundary hardening") 빌드로, local HEAD의 **조상**이었다(`git merge-base --is-ancestor 59e55d4 HEAD` = true). long-context admission 병합(`b2754b8`/`2c9faad`/`35eb219`/`5b95208`)이 그 이후라 기능 미배포 상태였다.
- 증상: `all-long-slot-full`에서 6 long이 long-slot 제한 없이 normal capacity로 전부 dispatch(peak `in_flight=6`, `mac-mlx-vllm=2`로 자기 `long_context_capacity=1` 초과), Edge 로그에 구조화 admission 필드 없음.
- 조치: 사용자 승인 하에 dev Edge를 현재 main `2d08d24`로 재배포(아래 재배포 절차)했다. source bug가 아니라 배포 stale이었다.

### 재배포 절차 (Edge 집중, 사용자 승인 후)

long-context admission은 Edge-side 로직이고 3 node가 healthy했으므로 전체 pool 재시작 대신 Edge 재배포로 범위를 좁혔다.

```text
runner clean sync: git reset --hard origin/main (59e55d4 -> 2d08d24), git clean -fd
pre-build test:    go test ./...  -> ALL ok (go1.26.3)
rebuild:           go build -trimpath -o build/dev-runtime/bin/edge ./apps/edge/cmd/edge  (21:30 build)
post-build:        config check OK, config refresh subcommand present
restart:           old pid 87233 정지, 신규 pid 3527 (Fx RUNNING), 로그 rotate
verify:            3 node(mac-codex/gx10-vllm/onexplayer-lemonade) 즉시 재연결, healthy (2/4/3=9)
```

### 배포 config gap 발견 및 보정

- 재배포 후에도 `all-long-slot-full`에서 6 long이 전부 dispatch(peak `in_flight=6`, `queued=0`)되어 queue가 안 잡혔다. 로그는 이번엔 `context_class:"long"`, `estimated_input_tokens:120018`을 정상 기록 → **분류는 동작**.
- 원인: 배포된 `build/dev-runtime/edge.yaml`의 provider에 `total_context_tokens`/`long_context_capacity`가 미설정(0)이라 long-slot 게이팅이 없었다. task 05가 예시 config/inventory만 정렬했고 실제 dev 배포 config엔 반영되지 않은 config gap이었다(source bug 아님).
- 보정(사용자 결정 반영): 배포 config에 `long_context_threshold_tokens: 30000`(사용자 요청값)과 provider별 `total_context_tokens`/`long_context_capacity`(gx10 262144/1, onexplayer 524288/2, mac 262144/1, inventory 기준)를 추가하고 `config refresh --mode apply`로 **무중단 live-apply**했다(dry-run 결과 전부 `applied`, `restart_required_paths: []` — task 02 live-apply 주장 검증). 3 node healthy 유지.

### post-fix 라이브 검증 (dev Edge=2d08d24, threshold=30000, long_cap gx10=1/onex=2/mac=1)

```text
$ ... --scenario normal-10
peak_in_flight=9  peak_queued=3   normal http_200=10/10   recovery in_flight=0/queued=0 OK

$ ... --scenario mixed   (LONG_CHARS=384000)
normal http_200=6/6 (head-of-line blocking 없음)
mid-run: long 4개가 long slot 정확 점유 mac=1/1 gx10=1/1 onexplayer=2/2, 동시에 normal 완료
recovery in_flight=0/queued=0 OK

$ ... --scenario all-long-slot-full   (LONG_CHARS=384000)
peak_in_flight=4 (long slot total=4로 캡; 이전 배포 stale/config-gap 때는 6)
peak_queued>0 (queue 발생; 이전 0)
Edge 로그: queue_reason="long_context_capacity_full" 2건 (6 long - 4 slot = 2 대기), 이후 slot 회복 시 dispatch
long http_200=6/6   recovery in_flight=0/queued=0 OK
```

- 분류 evidence(로그 `build/dev-runtime/bin/logs/edge.log`): `context_class:"long"`, `estimated_input_tokens:120018`, queued 요청 `queue_reason:"long_context_capacity_full"`.
- S09 수용 충족: normal 10-way capacity 도달·queue·회복, mixed에서 long slot 점유 중 normal 무차단 완료, all-long-slot-full에서 long slot 초과분 queue 대기 후 dispatch, 세 시나리오 모두 최종 `in_flight=0`/`queued=0` 회복.

### 후속 작업 (follow-up)

1. (관측성) Control Plane HTTP status view(`apps/control-plane/cmd/control-plane/http_views.go`의 `providerSnapshotView`)가 `long_in_flight`/`long_queued`/`long_context_capacity`를 노출하지 않는다. proto `ProviderSnapshot`·Edge relay에는 값이 있으나 JSON view에서 누락되어, long-slot 회복은 status로 직접 관측 불가하고 Edge 로그(`queue_reason`/`context_class`)로 재구성해야 한다. view 확장을 control-plane/status-logs 범위 follow-up으로 검토.
2. (threshold 정책 영속화/SDD) `long_context_threshold_tokens=30000`은 사용자 결정으로 **배포 dev config에만** 적용했다. tracked 기본값(`packages/go/config/config.go` 기본 100000, `configs/edge.yaml` 예시)과 SDD 반영은 별도 결정이다. 또한 threshold를 낮추면 "long slot 1개 = context_window(262144) 한 요청"이라는 D02/D03 슬롯 모델과 커플링 문제가 생긴다(30k 요청이 262k용 슬롯을 통째로 점유). long_cap을 KV 예산 기반으로 재정의할지 SDD 검토 필요.
3. (배포 config 재현성) dev 배포 config(`build/dev-runtime/edge.yaml`, untracked)에 long_context 필드가 없던 gap이 이번에 드러났다. dev-runtime-deploy 절차가 inventory의 long capacity 값을 배포 config에 확실히 반영하도록 절차/문서 보강 검토.

---

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

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail
  - completeness: Fail
  - test coverage: Fail
  - API contract: Pass
  - code quality: Pass
  - implementation deviation: Warn
  - verification trust: Fail
  - spec conformance: Fail
- 발견된 문제:
  - Required — `scripts/e2e-long-context-admission-smoke.sh:286`: `fire_and_wait` counts HTTP 200 responses but only logs the count and always returns success. As a result, `normal-10` and `all-long-slot-full` can exit 0 even when every request fails. Fix by making request success counts part of the function's return contract and requiring `normal-10` 10/10, `mixed` normal 6/6 plus long 4/4, and `all-long-slot-full` 6/6 before the scenario can pass.
  - Required — `scripts/e2e-long-context-admission-smoke.sh:315` and `scripts/e2e-long-context-admission-smoke.sh:340`: preflight records `edge config check` and provider identity checks but does not fail when config check fails or a required provider is missing. Fix by propagating config-check failure, requiring all three provider ids to be present, healthy, and summing to the documented capacity baseline before returning `PREFLIGHT OK`.
  - Required — `scripts/e2e-long-context-admission-smoke.sh:373`: the scenario PASS criteria documented in `agent-test/dev/long-context-admission-smoke.md:67` are not asserted. The script records `peak_in_flight`/`peak_queued`, but `normal-10` does not require peak `in_flight=9` and `queued>=1`, and `all-long-slot-full` does not require long-slot queue evidence. Fix by parsing the peaks file or returning peak values from polling, then failing when the documented peak/queue criteria are not met. The local mock check reproduced the bug: `all-long-slot-full` returned `rc=0` with `http_200=0/6`, `peak_in_flight=0`, and `peak_queued=0`.
  - Required — `agent-task/m-model-group-long-context-admission/06+01,02,03,04,05_capacity_smoke/CODE_REVIEW-cloud-G08.md:160`: the live post-fix evidence is summarized instead of preserving actual stdout/stderr or exact status/log evidence paths for each scenario. Because SDD S09 requires dev smoke script/output and final recovery snapshots, rerun after fixing the exit contract and paste actual command output or exact saved output files, status snapshots, and Edge log evidence paths/snippets.
- 다음 단계: FAIL follow-up plan/review를 작성해 smoke script exit contract와 evidence capture를 보강한 뒤 live dev provider pool smoke를 다시 수집한다.
