<!-- task=m-openai-compatible-think-control/05+01,02,03,04_dev_smoke plan=2 tag=REVIEW_REVIEW_TEST -->

# Code Review Reference - REVIEW_REVIEW_TEST

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a selected Milestone `구현 잠금 > 결정 필요` item, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Environment/secret/service setup, generic scope conflicts, loop exhaustion, and evidence gaps that a follow-up agent can close are normal follow-up issues, not user-review blockers by themselves.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record only the linked Milestone lock decision in `사용자 리뷰 요청` and stop for code-review.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## 개요

date=2026-07-03
task=m-openai-compatible-think-control/05+01,02,03,04_dev_smoke, plan=2, tag=REVIEW_REVIEW_TEST

## Roadmap Targets

- Milestone: `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-think-control.md`
- Task ids:
  - `dev-smoke`: 실제 dev provider pool에서 `think=false`, omitted default, `include_reasoning=false` 요청을 실행하고 provider raw trace와 Edge SSE를 비교한다.
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Archived plan: `agent-task/m-openai-compatible-think-control/05+01,02,03,04_dev_smoke/plan_cloud_G07_1.log`
- Archived review: `agent-task/m-openai-compatible-think-control/05+01,02,03,04_dev_smoke/code_review_cloud_G07_1.log`
- Verdict: FAIL
- Required summary:
  - `code_review_cloud_G07_1.log` records that `mac-mlx-vllm` `think=false` returned a normal stream with Edge SSE `reasoning_content` nonempty 302 chunks and provider raw `reasoning_len>0` for 302/332 parsed chunks.
  - `code_review_cloud_G07_1.log` records that `onexplayer-lemonade` `think=false` returned a normal stream with Edge SSE `reasoning_content` nonempty 2067 chunks and provider raw `reasoning_len>0` for 2067/2283 trace lines.
  - Active plan expectation required `think=false` to produce no provider reasoning and no Edge `reasoning_content`; SDD S05 requires provider raw trace and Edge SSE generation/exposure state to match the defined expectation.
  - SDD and contract allow unsupported provider combinations only when they become a clear compatibility error or defined fallback, not a silent successful stream with reasoning.
- Affected files:
  - Likely source: `apps/node/internal/adapters/openai_compat/openai_compat.go`
  - Likely tests: `apps/node/internal/adapters/openai_compat/openai_compat_test.go`, `apps/edge/internal/openai/server_test.go`
  - Likely contract/docs if unsupported/fallback policy changes: `agent-contract/outer/openai-compatible-api.md`, `docs/openai-compatible-api-contract.md`
  - If a provider capability/config field is added: `packages/go/config/config.go`, `configs/edge.yaml`, `agent-contract/inner/edge-config-runtime-refresh.md`
  - Active evidence artifact to fill: `agent-task/m-openai-compatible-think-control/05+01,02,03,04_dev_smoke/CODE_REVIEW-cloud-G07.md`
- Verification evidence already trusted from prior loop:
  - Remote source ref `eea8dd0`; remote checkout clean and aligned with `origin/main`.
  - Remote `go test ./...` passed after restore in the previous loop.
  - Provider-isolated routing via `models["qwen3.6:35b"].providers` apply worked without restart-required paths.
  - `gx10-vllm` `think=false` produced no provider reasoning and no Edge `reasoning_content`.
  - `include_reasoning=false` suppressed Edge SSE reasoning exposure on all three providers while preserving content and `[DONE]`.
  - Final previous-loop restore returned all three nodes/providers to connected/healthy/recovered state.
- Allowed archive reread:
  - Read only the two archived files listed above if exact previous-loop context is needed. Do not scan `agent-task/archive/**`.
- Roadmap carryover:
  - `dev-smoke` remains incomplete until provider별 `think=false` behavior is either raw no-reasoning or an explicit unsupported/fallback outcome, and the provider matrix is re-recorded after any code/docs/config change.

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

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 source/evidence와 대조하고, `검증 결과` 섹션의 출력이 plan의 S05 요구와 unsupported/fallback 정책을 충족하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.

1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-openai-compatible-think-control`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [REVIEW_REVIEW_TEST-1] Provider Disable Capability Probe | [x] |
| [REVIEW_REVIEW_TEST-2] Compatibility Policy Implementation | [x] |
| [REVIEW_REVIEW_TEST-3] Dev-Runtime Rebuild And S05 Re-Smoke | [x] |

## 구현 체크리스트

- [x] mac vLLM-MLX와 OneXPlayer Lemonade의 request-level thinking disable 지원 여부를 direct provider probe 또는 equivalent trace로 확인하고, 지원 field 또는 미지원 결론을 기록한다.
- [x] probe 결과에 따라 Node provider mapping을 수정하거나, 미지원 provider에서 `think=false`가 조용히 성공하지 않도록 compatibility error/명시 fallback 정책을 구현하고 계약/문서를 갱신한다.
- [x] `gx10-vllm`의 기존 `think=false` 성공 경로와 `include_reasoning=false` 노출 억제를 단위/통합 테스트로 보존한다.
- [x] 변경한 source ref로 dev-runtime binary를 rebuild/redeploy한 뒤 provider-isolated S05 matrix를 재실행하고, `mac-mlx-vllm`, `gx10-vllm`, `onexplayer-lemonade` 각각의 final judgment를 기록한다.
- [x] 임시 config/trace 변경을 원복하고, 최종 `go test ./...`, `/v1/models`, 3-node connected/provider healthy/recovered 상태를 기록한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 실행 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

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

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [x] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
- [ ] USER_REVIEW가 연결된 Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.

## 계획 대비 변경 사항

- **Probe 방식**: 계획은 provider-isolated IOP routing + raw trace 또는 direct provider probe를 허용했다. 실제로는 각 provider endpoint를 direct로 probe했다(mac-mlx-vllm `http://127.0.0.1:8002/v1`은 `edge.yaml`에서 읽은 `Authorization` 헤더를 원격 셸 변수로만 주입하고 값을 출력하지 않음, gx10/lemonade는 auth 없음). Non-stream + streaming 두 형태를 모두 측정해 provider별 disable 지원 여부를 판정했다. Node stream trace(`IOP_OPENAI_COMPAT_TRACE_STREAM`)는 이번에는 사용하지 않았는데, 이번 루프의 판정 대상은 "provider가 실제로 어떤 request field에 반응하는가"이고 이는 IOP를 우회한 direct probe로 더 깨끗하게 확인되기 때문이다. provider raw generation 근거는 direct probe 값으로 대체 기록한다.
- **provider raw trace 재수집 생략 사유**: 이전 루프(`code_review_cloud_G07_1.log`)는 provider가 계속 reasoning을 "생성"하는지 증명하려고 node 로그를 추출했다. 이번 fix 이후 `think=false`의 결과가 (a) mac은 Edge SSE에서 명시 error, (b) lemonade/gx10은 Edge SSE `reasoning_content` 0이라는 관측 자체가 판정 근거이므로, Windows 대용량 로그 구간 추출 같은 heavy trace는 불필요했다. provider 레벨 생성 억제 근거는 direct provider probe(아래 검증 결과)로 별도 확보했다.
- **Redeploy 범위 축소**: dev-runtime-deploy 스킬은 4개 binary 전량 rebuild/redeploy를 기준으로 한다. 이번 소스 변경은 `apps/node/internal/adapters/openai_compat/openai_compat.go` 한 파일뿐이고 `vllm`(gx10) 매핑 동작은 바뀌지 않으므로, functional 변경이 있는 `mac-codex-node`(mac native binary)와 `onexplayer-lemonade-node`(windows amd64 binary)만 rebuild/redeploy했다. `gx10-vllm-node`(linux arm64) binary는 소스 동작 불변이라 재배포하지 않고 재-smoke로 무회귀만 확인했다. Edge binary도 변경 없음.
- **원격 checkout dirty 유지**: `/Users/toki/agent-work/iop-dev` 원격 checkout에 변경 소스 2파일(`openai_compat.go`, `openai_compat_test.go`)을 반영해 dirty 상태로 두고 그 기준으로 binary를 빌드/배포했다. commit/push는 리뷰-종결 단계 책임이므로 이 루프에서 수행하지 않았다. plan의 "source changed" 재-smoke 기대와 일치한다. 원본 mac binary는 `bin/iop-node.eea8dd0.bak`, onexplayer 원본은 `iop-node.exe.prev-fix-<ts>`로 롤백 가능하게 보존했다.
- **Secret masking**: mac-mlx-vllm provider `Authorization` 헤더, edge `bearer_token`, onexplayer node registration 값은 원격 셸 변수로만 사용하고 이 문서/명령 로그에 원문을 남기지 않았다.

## 주요 설계 결정

- **Probe 결론(REVIEW_REVIEW_TEST-1)**:
  - **Lemonade = 지원(via `chat_template_kwargs.enable_thinking=false`)**: 현재 매핑인 top-level `think:false`는 이 Lemonade 빌드가 무시한다(streaming reasoning 400 deltas 유지). `chat_template_kwargs.enable_thinking=false`를 보내면 reasoning 0 + content 정상 생성으로 깨끗하게 disable된다. Lemonade는 Qwen3 GGUF를 서빙하며 chat template kwargs를 반영한다.
  - **vLLM-MLX = 미지원(current runtime)**: `enable_thinking=false`가 생성 토큰 수는 줄이지만(streaming 397→220 tok), 이 mlx 런타임의 streaming reasoning parser가 응답 전체를 `reasoning_content`로 라벨링하고 content를 0으로 만든다. 따라서 어떤 request field로도 streaming에서 reasoning-free 응답을 만들 수 없다. `/no_think` soft switch, `reasoning_effort=none` 역시 효과 없음.
- **매핑 통합(REVIEW_REVIEW_TEST-2)**: `vllm`/`vllm-mlx`/`lemonade` 세 provider의 think-control을 모두 `chat_template_kwargs.enable_thinking`(+ `thinking_token_budget`) 경로로 통합했다. Lemonade의 top-level `think`/`reasoning_effort`/`thinking_token_budget` 전달을 제거했고, Lemonade의 `reasoning_effort=low|medium|high`도 vLLM과 동일하게 `unsupported think control` error로 처리한다(Qwen3 template에 effort level kwarg가 없고 top-level은 무시됨).
- **vLLM-MLX disable 시 명시 error**: `vllm-mlx` provider에서 `think=false` 또는 `reasoning_effort=none`(생성 disable 요청)이 오면 `buildRequestBody`가 `unsupported think control: provider "vllm-mlx" cannot disable reasoning generation for streaming responses (think=false / reasoning_effort=none)`를 반환한다. 이는 기존 vLLM `reasoning_effort=low` 미지원 error와 동일한 경로(Node adapter error → Edge SSE `{"error":{"type":"run_error",...}}`)를 재사용하므로 Edge 측 신규 처리가 필요 없다. `think=true`/budget-only는 error 없이 `enable_thinking=true`로 유지해 정상 reasoning 요청을 깨지 않는다.
- **fallback 대신 error 선택 근거**: vLLM-MLX에 대해 "documented fallback"(예: enable_thinking=false + 노출 억제)은 이 런타임이 답변까지 `reasoning_content`로 라벨링하기 때문에 답변 자체가 사라져 성립하지 않는다. 따라서 SDD State Machine의 `unsupported -> error` 경로를 택해, 공개 `think=false` 요청을 조용한 200 reasoning stream으로 성공시키지 않고 명시 compatibility error로 반환한다.
- **계약/문서**: `agent-contract/outer/openai-compatible-api.md`의 "Provider별 think-control 정책"을 vLLM/vLLM-MLX/Lemonade로 분리해 갱신했다(vLLM-MLX disable → error, Lemonade → chat_template_kwargs). `docs/openai-compatible-api-contract.md`는 계약 원문 포인터라 별도 수정 없이 반영된다. provider capability config flag는 도입하지 않았으므로 `packages/go/config`, `configs/edge.yaml`, `agent-contract/inner/edge-config-runtime-refresh.md`는 건드리지 않았다.

## 사용자 리뷰 요청

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

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

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

- mac vLLM-MLX와 OneXPlayer Lemonade probe가 secret 없이 실제 request-level generation disable 지원 여부를 판정했는지 확인한다.
- provider가 unsupported로 결론났다면 `think=false`가 정상 200 reasoning stream으로 남지 않고 명확한 error 또는 문서화된 fallback으로 처리되는지 확인한다.
- `gx10-vllm`의 기존 `think=false` raw no-reasoning 경로가 회귀하지 않았는지 확인한다.
- `include_reasoning=false`는 세 provider에서 Edge SSE reasoning exposure를 계속 억제하는지 확인한다.
- S05 matrix가 provider별 omitted default, `think=false`, `include_reasoning=false`를 모두 포함하고, final judgment가 SDD/contract 기대와 일치하는지 확인한다.
- 임시 trace/config 변경이 원복되고 최종 3-node/provider 상태가 healthy/recovered인지 확인한다.

## 검증 결과

_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._

필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.

### REVIEW_REVIEW_TEST-1 중간 검증
```bash
$ ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && git status --short --branch && git log --oneline -1'
## main...origin/main
eea8dd0 feat: add think-control API fields and dev smoke tests
# (probe 시작 시점, 소스 변경 전 clean)

$ ssh toki@toki-labs.com 'curl -fsS http://127.0.0.1:18001/edges/edge-toki-labs-dev/status | jq "{...}"'
nodes: mac-codex-node/gx10-vllm-node/onexplayer-lemonade-node 모두 connected=true
providers: mac-mlx-vllm/gx10-vllm/onexplayer-lemonade 모두 health=healthy, in_flight=0, queued=0
```

Direct provider probe (secret masking: mac Authorization 헤더는 `edge.yaml`에서 원격 셸 변수로만 주입, 값 미출력). 판정용 non-stream + streaming 측정:

```text
# NON-STREAM (max_tokens=300), reasoning_content_len / content_len / finish
mac  baseline                     : reasoning=0   content=768 finish=length   # mlx는 non-stream에서 답변을 content에 담음
mac  chat_template_kwargs.enable_thinking=false : reasoning=0 content=199 finish=stop   # 생성은 짧아짐
mac  /no_think                    : reasoning=0   content=764 finish=length   # 무효
mac  reasoning_effort=none        : reasoning=0   content=806 finish=length   # 무효
lem  baseline                     : reasoning=753 content=0
lem  think=false (현행 매핑)       : reasoning=717 content=0   finish=length   # 무시됨
lem  chat_template_kwargs.enable_thinking=false : reasoning=0 content=202 finish=stop   # 지원! 깨끗한 disable
lem  /no_think                    : reasoning=812 무효
lem  reasoning_effort=none        : reasoning=747 무효

# STREAMING (reasoning/content delta 및 chars)
mac  baseline stream              : reasoning_deltas=344
mac  enable_thinking=false stream : reasoning_deltas=89(원시), 전량 reasoning_content 라벨링
mac  enable_thinking=false 완주(max_tokens 1200): reasoning_chars=512 content_chars=0 completion_tokens=220
mac  baseline 완주               : reasoning_chars=942 content_chars=23 completion_tokens=397
lem  baseline stream              : reasoning_deltas=400
lem  think=false stream           : reasoning_deltas=400   # 무시됨
lem  enable_thinking=false stream : reasoning_deltas=0  content_deltas=88   # 지원

결론: Lemonade는 chat_template_kwargs.enable_thinking로 disable 지원. vLLM-MLX는 streaming에서 전체 출력을
reasoning_content로 라벨링하고 enable_thinking=false로도 reasoning-free 응답을 못 만드는 미지원 런타임.
```

### REVIEW_REVIEW_TEST-2 중간 검증
```bash
$ go test -count=1 ./apps/node/internal/adapters/openai_compat ./apps/edge/internal/openai
ok  	iop/apps/node/internal/adapters/openai_compat	0.016s
ok  	iop/apps/edge/internal/openai	1.567s

# 원격 checkout(변경 소스 반영)에서도 동일 통과:
$ ssh toki@toki-labs.com 'export PATH=/opt/homebrew/bin:$PATH && cd .../iop-dev && go test -count=1 ./apps/node/internal/adapters/openai_compat'
ok  	iop/apps/node/internal/adapters/openai_compat	0.487s
```

### REVIEW_REVIEW_TEST-3 중간 검증
```bash
$ ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config check'
OK build/dev-runtime/edge.yaml

$ ssh toki@toki-labs.com 'curl -fsS -H "Authorization: Bearer <masked>" http://127.0.0.1:18083/v1/models'
{"object":"list","data":[{"id":"qwen3.6:35b","object":"model","created":1783110783,"owned_by":"iop"}]}

$ ssh toki@toki-labs.com 'curl -fsS http://127.0.0.1:18001/edges/edge-toki-labs-dev/status | jq "{...}"'
nodes: 3개 모두 connected=true
providers: mac-mlx-vllm(cap3)/gx10-vllm(cap4)/onexplayer-lemonade(cap3) 모두 healthy, in_flight=0, queued=0
```

Rebuild/redeploy: 변경 소스 2파일을 원격 checkout에 반영 → `go build`로 mac native `iop-node`, cross-build `iop-node-windows-amd64.exe` 생성 → `mac-codex-node`(mac, pid 52757→24030)와 `onexplayer-lemonade-node`(windows, WMI `Win32_Process.Create`, pid 31584→51776) 재시작, 세 node 모두 재연결/healthy 확인. `gx10-vllm-node`는 소스 동작 불변이라 재배포하지 않음.

Provider-isolated S05 re-smoke (`models["qwen3.6:35b"].providers`를 provider 1개로 축소한 candidate config를 `config refresh --mode apply`로 적용, `restart_required_paths:[]`). `/v1/chat/completions` stream, prompt `"What is 17 times 23? Reason briefly, then give the final number."`:

| Provider | Case | Edge SSE 관측 | Provider raw (direct probe) | Judgment |
|----------|------|---------------|------------------------------|----------|
| mac-mlx-vllm | omitted_default | reasoning_deltas=351, [DONE] 정상 | 생성함(baseline reasoning 942ch) | PASS — 기본 동작 유지 |
| mac-mlx-vllm | think=false | reasoning_deltas=0, content_deltas=0, **`{"error":{"type":"run_error","message":"...unsupported think control: provider \"vllm-mlx\" cannot disable reasoning generation for streaming responses (think=false / reasoning_effort=none)"}}`** | (요청이 provider에 도달 전 error) | PASS — 조용한 200 reasoning stream이 아니라 명시 compatibility error |
| mac-mlx-vllm | include_reasoning=false | reasoning_deltas=0(노출 억제), [DONE] 정상 | 생성은 계속(direct probe 기준) | PASS — Edge 노출만 억제 |
| gx10-vllm | omitted_default | reasoning_deltas=400, [DONE] 정상 | 생성함 | PASS |
| gx10-vllm | think=false | reasoning_deltas=0, **content_deltas=96**, [DONE] 정상 | enable_thinking=false로 생성 자체 비활성 | PASS — 무회귀(기대대로 clean disable) |
| gx10-vllm | include_reasoning=false | reasoning_deltas=0, content_deltas=20, [DONE] 정상 | 생성은 계속 | PASS — 노출만 억제 |
| onexplayer-lemonade | omitted_default | reasoning_deltas=400, [DONE] 정상 | 생성함(baseline reasoning 753ch) | PASS |
| onexplayer-lemonade | think=false | reasoning_deltas=0, **content_deltas=113**, [DONE] 정상 | enable_thinking=false → direct probe reasoning 0, content 202 | PASS — **fix 적용됨**(이전 루프 2067 reasoning → 0) |
| onexplayer-lemonade | include_reasoning=false | reasoning_deltas=0(노출 억제), [DONE] 정상 | 생성은 계속 | PASS — 노출만 억제 |

Restore: candidate config 3개 적용 후 원본 `edge.yaml`(3-provider 전체)을 `config refresh --mode apply`로 재적용(`node_results: applied/applied/applied`). 임시 `edge.route-active.yaml`, mac 빌드 staging `bin/iop-node-windows-amd64.exe.new`, onexplayer `iop-node.new.exe` 삭제. 원본 binary는 `bin/iop-node.eea8dd0.bak`, onexplayer `iop-node.exe.prev-fix-<ts>`로 보존.

### 최종 검증
```bash
$ go test -count=1 ./apps/node/internal/adapters/openai_compat ./apps/edge/internal/openai
ok  	iop/apps/node/internal/adapters/openai_compat	0.016s
ok  	iop/apps/edge/internal/openai	1.567s

$ ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && git status --short --branch && git log --oneline -1'
## main...origin/main
 M apps/node/internal/adapters/openai_compat/openai_compat.go
 M apps/node/internal/adapters/openai_compat/openai_compat_test.go
eea8dd0 feat: add think-control API fields and dev smoke tests
# (source changed 재-smoke 기준: 변경 소스가 원격 checkout에 반영된 dirty 상태. commit/push는 리뷰-종결 책임)

$ ssh toki@toki-labs.com 'export PATH=/opt/homebrew/bin:$PATH && cd /Users/toki/agent-work/iop-dev && go test ./...'
GO_TEST_EXIT=0
# 전 패키지 통과(ok 33 packages, FAIL/panic 없음)

$ ssh toki@toki-labs.com 'curl -fsS http://127.0.0.1:18001/edges/edge-toki-labs-dev/status | jq "{...}"'
{
  "nodes": [
    {"node_id": "mac-codex-node", "connected": true},
    {"node_id": "gx10-vllm-node", "connected": true},
    {"node_id": "onexplayer-lemonade-node", "connected": true}
  ],
  "providers": [
    {"id": "mac-mlx-vllm", "capacity": 3, "in_flight": 0, "queued": 0, "health": "healthy", "served_models": ["mlx-community/Qwen3.6-35B-A3B-4bit"]},
    {"id": "gx10-vllm", "capacity": 4, "in_flight": 0, "queued": 0, "health": "healthy", "served_models": ["nvidia/Qwen3.6-35B-A3B-NVFP4"]},
    {"id": "onexplayer-lemonade", "capacity": 3, "in_flight": 0, "queued": 0, "health": "healthy", "served_models": ["Qwen3.6-35B-A3B-MTP-GGUF"]}
  ]
}
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

Sections and their ownership:

| 섹션 | 소유자 | 설명 |
|------|--------|------|
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
| Roadmap Targets | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 수정하지 않음; PASS 시 code-review가 `complete.log`의 `Roadmap Completion`으로 복사 |
| Archive Evidence Snapshot | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트의 기본 이전 루프 컨텍스트; 추가 확인이 필요할 때 여기에 명시된 archive 파일만 좁게 읽음 |
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` -> `[x]` 체크만 구현 에이전트가 수행 |
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` -> `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
| 코드리뷰 전용 체크리스트 | Review agent only | 구현 에이전트는 수정하거나 체크하지 않음 |
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 차단할 때만 채움 |
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
| 검증 결과 | 구현 에이전트가 채움 | 실행 출력만 구현 에이전트가 채움 |
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |

## 코드리뷰 결과

- 종합 판정: PASS
- 차원별 평가:
  - Correctness: Pass
  - Completeness: Pass
  - Test coverage: Pass
  - API contract: Pass
  - Code quality: Pass
  - Implementation deviation: Pass
  - Verification trust: Pass
  - Spec conformance: Pass
- 발견된 문제:
  - Nit(직접 수정됨): `docs/edge-local-dev-guide.md:240`의 think-control smoke 안내가 vLLM-MLX `think=false` 명시 error 및 Lemonade `reasoning_effort=low|medium|high` unsupported 정책과 맞지 않았다. 리뷰 중 provider-isolated 기대 결과와 unsupported 판정을 반영하도록 문구를 갱신했다.
- 다음 단계: PASS 종결. active plan/review를 `.log`로 아카이브하고 `complete.log` 작성 후 task directory를 `agent-task/archive/2026/07/` 아래로 이동한다.
