<!-- task=m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke plan=2 tag=REVIEW_REVIEW_TEST -->

# Plan - REVIEW_REVIEW_TEST

## 이 파일을 읽는 구현 에이전트에게

`CODE_REVIEW-cloud-G08.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 반드시 채운다. 검증 명령을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 review ready로 보고한다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review-skill 전용이다. 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 막을 때만 review stub의 `사용자 리뷰 요청` 섹션을 채우고 멈춘다. 외부 환경/secret/service blocker, 일반 범위 조정, 증거 공백은 사용자 리뷰가 아니라 검증 결과나 후속 plan으로 기록한다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다.

## 배경

이전 review loop는 docs/dev-runtime command drift 일부를 고쳤지만 SDD S16/S17 field evidence를 만들지 못했다. 원격 `/Users/toki/agent-work/iop-dev` checkout은 dirty/divergent 상태이고 실행 중 dev-runtime binary가 이번 config refresh 구현보다 오래되어 `config refresh` 명령을 제공하지 않는다. 이번 follow-up은 기존 원격 checkout을 reset하지 않고 별도 clean review workdir에서 현재 코드 artifact를 빌드한 뒤, 실제 3 Node reconnect와 refresh/concurrency evidence를 수집한다.

## 사용자 리뷰 요청 흐름

선택된 Milestone lock 결정만 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 중 직접 사용자에게 묻지 말고, code-review가 해당 요청을 검증한 뒤 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## Archive Evidence Snapshot

- Prior active task: `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke`
- Archived plan logs:
  - `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/plan_cloud_G08_0.log`
  - `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/plan_cloud_G08_1.log`
- Archived review logs:
  - `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/code_review_cloud_G08_0.log`
  - `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/code_review_cloud_G08_1.log`
- Verdicts: FAIL, FAIL
- Required summary:
  - S16 `field-reconnect` evidence is still missing: `reconnect-after-status.json`, `reconnect-after-tcp.txt`, and `reconnect-pids.txt` were missing or empty.
  - S17 `field-refresh` evidence is still missing: remote `edge config` exposed only `check/init/print`, and `refresh-apply.json`, `refresh-pid.txt`, `refresh-concurrent-4.jsonl` were missing.
  - Remote `/Users/toki/agent-work/iop-dev` is dirty/divergent and lacks `apps/edge/internal/bootstrap/refresh_admin.go`; do not reset or overwrite it.
  - Reviewer repaired dev-runtime edge id wording in `docs/edge-local-dev-guide.md` and ignored local test profile `agent-test/local/edge-smoke.md` from `edge-toki-labs` to `edge-toki-labs-dev`.
- Affected files/areas:
  - Remote clean review workdir under `/Users/toki/agent-work/iop-field-review`
  - Remote ignored dev-runtime configs copied from `/Users/toki/agent-work/iop-dev/build/dev-runtime/*.yaml`
  - `CODE_REVIEW-cloud-G08.md`
- Verification evidence from prior loop:
  - Remote HEAD was `7398f32 update roadmap: archive inference-provider-extension milestone and update phase docs`.
  - Remote `build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config --help` listed only `check`, `init`, `print`.
  - Remote Control Plane status for `edge-toki-labs-dev` showed only `mac-codex-node` and `onexplayer-lemonade-node`.
- Roadmap carryover: `field-reconnect`, `field-refresh`, and `docs` remain incomplete until this follow-up PASS writes `Roadmap Completion`.
- Narrow archive reread allowed if needed: only the four archived logs listed above.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/update-plane-self-update-foundation/milestones/runtime-reconnect-config-refresh.md`
- Task ids:
  - `field-reconnect`: `toki-labs.com` dev-runtime에서 Edge restart 후 GX10 Linux Node와 OneXPlayer Windows Node가 bootstrap 재실행 없이 재접속한다.
  - `field-refresh`: `gx10-vllm=4`, `onexplayer-lemonade=3` capacity 변경을 refresh로 반영하고 Edge process restart 없이 `qwen3.6:35b` 동시 4개 요청이 성공한다.
  - `docs`: bootstrap/reconnect/refresh 운영 방법과 제한 사항이 `apps/edge/README.md`, `docs/edge-local-dev-guide.md`, agent-test field 기준에 반영된다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-roadmap/current.md`
- `agent-roadmap/phase/update-plane-self-update-foundation/milestones/runtime-reconnect-config-refresh.md`
- `agent-roadmap/sdd/update-plane-self-update-foundation/runtime-reconnect-config-refresh/SDD.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `Makefile`
- `apps/edge/README.md`
- `docs/edge-local-dev-guide.md`
- `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/plan_cloud_G08_1.log`
- `agent-task/m-runtime-reconnect-config-refresh/07+01,03,04,05,06_field_docs_smoke/code_review_cloud_G08_1.log`

### SDD 기준

- SDD: `agent-roadmap/sdd/update-plane-self-update-foundation/runtime-reconnect-config-refresh/SDD.md`
- 상태: `[승인됨]`, SDD 잠금 해제, 사용자 리뷰 없음.
- Target scenarios:
  - S16 -> `field-reconnect`: Edge restart 후 bootstrap 재실행 없이 3개 Node 연결 회복.
  - S17 -> `field-refresh`: `gx10-vllm=4`, `onexplayer-lemonade=3` refresh apply 후 Edge restart 없이 `qwen3.6:35b` 동시 4개 요청 성공.
  - S18 -> `docs`: docs diff와 agent-test field rule diff.
- Evidence Map rows:
  - S16: remote dev field status와 TCP connection evidence.
  - S17: remote dev 4 concurrent OpenAI-compatible requests와 refresh result evidence.
  - S18: docs diff와 agent-test field rule diff.
- 이 follow-up은 clean remote artifact rebuild를 먼저 완료해야 S16/S17 evidence가 의미를 가진다. S18은 tracked docs와 ignored local field profile의 edge id drift를 reviewer가 보정했으므로 최종 검증에서 다시 확인한다.

### 테스트 환경 규칙

- `test_env=local`.
- `agent-test/local/rules.md`를 읽었다. field/bootstrap, 외부 runtime evidence는 원격 runner `ssh toki@toki-labs.com`의 `/Users/toki/agent-work/iop-dev` 기준이지만, 기존 checkout이 dirty하므로 이번 plan은 별도 `/Users/toki/agent-work/iop-field-review` workdir를 사용한다.
- Matched profile: `agent-test/local/edge-smoke.md`.
- 적용 기준: Control Plane status `http://127.0.0.1:18001`, dev-runtime Edge id `edge-toki-labs-dev`, Edge OpenAI-compatible `http://toki-labs.com:18083/v1`, Edge-Node TCP `toki-labs.com:18084`, model alias `qwen3.6:35b`, capacity `gx10-vllm=4`, `onexplayer-lemonade=3`.
- `<확인 필요>` 값 없음.
- token/API key/private endpoint 원문은 tracked docs, roadmap, review output에 기록하지 않는다.

### 테스트 커버리지 공백

- `field-reconnect`: S16 remote field evidence가 없다.
- `field-refresh`: S17 remote refresh apply, PID 유지, concurrent 4 request evidence가 없다.
- `docs`: reviewer가 edge id drift를 보정했으나, 최종 field evidence와 모순되지 않는지 다시 확인해야 한다.

### 심볼 참조

- none. 이 follow-up은 Go symbol rename/remove를 하지 않는다.

### 분할 판단

- split decision policy는 이미 적용된 Milestone split subtask를 유지한다.
- 공유 task group: `m-runtime-reconnect-config-refresh`.
- 선택 subtask: `07+01,03,04,05,06_field_docs_smoke`.
- Direct predecessors `01`, `03`, `04`, `05`, `06`는 이전 plan에서 archive complete.log로 충족 확인됐다. 이번 follow-up은 같은 active subtask에서 field evidence만 닫는다.

### 범위 결정 근거

- 기존 원격 `/Users/toki/agent-work/iop-dev` dirty checkout을 reset, checkout, clean, pull --rebase, force overwrite하지 않는다.
- 별도 clean review workdir와 ignored runtime configs만 사용한다.
- Provider token, API key, private endpoint 원문을 출력하지 않는다.
- Field evidence 중 실제 code defect가 발견되면 이 plan 안에서 새 Go 기능을 수정하지 말고 code-review에서 별도 Required로 분리한다.

### 빌드 등급

- `cloud-G08`: 원격 runner, clean artifact 재빌드, process lifecycle, multi-host Node reconnect, provider pool runtime, concurrent OpenAI-compatible request evidence가 중심이라 local bounded verification 조건을 만족하지 않는다.

## 구현 체크리스트

- [ ] `REVIEW_REVIEW_TEST-1` 원격 dirty checkout을 보존하면서 clean review workdir를 만들고 현재 코드로 dev-runtime binaries를 재빌드한다. 검증: remote `edge config refresh --help`가 노출되고 `build/dev-runtime/bin/edge config check`가 통과한다.
- [ ] `REVIEW_REVIEW_TEST-2` clean dev-runtime으로 S16/S17 field evidence를 수집한다. 검증: Edge restart 후 3 Node reconnect evidence, refresh dry-run/apply JSON, Edge PID 유지, `/healthz`, `/v1/models`, 4-line concurrent JSONL이 모두 존재한다.
- [ ] 최종 검증 명령을 모두 실행하고 실제 stdout/stderr를 `CODE_REVIEW-cloud-G08.md`에 붙여 넣는다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

`REVIEW_REVIEW_TEST-1`이 먼저 완료되어야 `REVIEW_REVIEW_TEST-2`의 evidence가 유효하다. 원격 dirty checkout 보호가 실패하면 field smoke를 진행하지 않는다.

### [REVIEW_REVIEW_TEST-1] Clean Remote Dev-Runtime Rebuild

문제: `code_review_cloud_G08_1.log:110`에 따르면 원격 checkout은 이번 feature 이전 상태이고, `code_review_cloud_G08_1.log:337`의 진단에서 `edge config refresh`가 존재하지 않는다.

해결 방법: 기존 `/Users/toki/agent-work/iop-dev`를 건드리지 않고, 로컬 `HEAD`를 tar stream으로 별도 `/Users/toki/agent-work/iop-field-review`에 풀어 clean workdir를 만든다. 기존 ignored dev-runtime YAML만 복사하고, remote macOS에서 Edge/Control Plane/mac Node binary와 GX10 Linux용 Node binary를 빌드한다.

수정 파일 및 체크리스트:

- [ ] `/Users/toki/agent-work/iop-field-review`를 새로 만들고 로컬 `HEAD` source를 전송한다.
- [ ] `/Users/toki/agent-work/iop-dev/build/dev-runtime/*.yaml`을 새 workdir의 `build/dev-runtime/`로 복사한다.
- [ ] `build/dev-runtime/bin/edge`, `control-plane`, `iop-node`, `iop-node-linux-arm64`를 빌드한다.
- [ ] `apps/edge/internal/bootstrap/refresh_admin.go` 존재와 `edge config refresh --help` 출력을 기록한다.
- [ ] token/API key/private endpoint 원문을 출력하지 않는다.

테스트 작성: 새 automated test는 작성하지 않는다. 이 항목은 field runtime artifact 준비다.

중간 검증:

```bash
git archive --format=tar HEAD | ssh toki@toki-labs.com 'set -euo pipefail
REVIEW_ROOT=/Users/toki/agent-work/iop-field-review
SOURCE_RUNTIME=/Users/toki/agent-work/iop-dev/build/dev-runtime
rm -rf "$REVIEW_ROOT"
mkdir -p "$REVIEW_ROOT"
tar -xf - -C "$REVIEW_ROOT"
cd "$REVIEW_ROOT"
mkdir -p build/dev-runtime/bin build/dev-runtime/logs /tmp/iop-field-evidence
cp "$SOURCE_RUNTIME"/*.yaml build/dev-runtime/
test -f apps/edge/internal/bootstrap/refresh_admin.go
/opt/homebrew/bin/go build -trimpath -o build/dev-runtime/bin/edge ./apps/edge/cmd/edge
/opt/homebrew/bin/go build -trimpath -o build/dev-runtime/bin/control-plane ./apps/control-plane/cmd/control-plane
/opt/homebrew/bin/go build -trimpath -o build/dev-runtime/bin/iop-node ./apps/node/cmd/node
GOOS=linux GOARCH=arm64 /opt/homebrew/bin/go build -trimpath -o build/dev-runtime/bin/iop-node-linux-arm64 ./apps/node/cmd/node
build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config check | tee /tmp/iop-field-evidence/review-config-check.txt
build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config refresh --help | tee /tmp/iop-field-evidence/review-config-refresh-help.txt
printf "review_root=%s\n" "$REVIEW_ROOT"
'
```

Expected: command exits 0, `review-config-check.txt` is nonempty, `review-config-refresh-help.txt` shows refresh flags including `--mode`, and no token/API key/private endpoint value is printed.

### [REVIEW_REVIEW_TEST-2] Field Reconnect And Refresh Evidence

문제: `code_review_cloud_G08_1.log:73`와 `code_review_cloud_G08_1.log:416`에 따르면 S16/S17 evidence files are missing or empty. Remote status recheck showed only `mac-codex-node` and `onexplayer-lemonade-node`, so S16 still lacks 3 Node reconnect evidence.

해결 방법: Clean review workdir binaries로 CP/Edge/mac Node baseline을 시작하고, GX10 Linux Node는 macOS Edge host에서 실행하지 않는다. Linux field host에는 `iop-node-linux-arm64`와 `node-gx10-vllm.yaml`을 secret 출력 없이 전달해 실행한다. 이후 Edge만 재시작해 3 Node reconnect를 확인하고, 같은 Edge PID에서 refresh dry-run/apply 및 동시 4 요청 evidence를 수집한다.

수정 파일 및 체크리스트:

- [ ] 기존 dev-runtime listener/process를 review run 전에 안전하게 종료한다. 종료 대상은 `/Users/toki/agent-work/iop-dev/build/dev-runtime` 또는 `/Users/toki/agent-work/iop-field-review/build/dev-runtime` config를 사용하는 CP/Edge/Node process로 한정한다.
- [ ] CP/Edge/mac-codex/onexplayer Node를 `/Users/toki/agent-work/iop-field-review/build/dev-runtime`에서 시작한다.
- [ ] GX10 Linux host에는 Linux ARM64 Node binary와 `node-gx10-vllm.yaml`을 전달하고, 해당 host에서 Node를 시작한다. token/config 원문을 출력하지 않는다.
- [ ] `edge-toki-labs-dev` status before/after에 `mac-codex-node`, `gx10-vllm-node`, `onexplayer-lemonade-node`가 모두 포함된다.
- [ ] Edge restart 전후 TCP evidence와 `bootstrap_rerun=none` pids evidence를 저장한다.
- [ ] Refresh dry-run/apply JSON, Edge PID before/after 동일성, `/healthz`, `/v1/models`, 4-line concurrent JSONL을 저장한다.

테스트 작성: 새 automated test는 작성하지 않는다. This is SDD S16/S17 field evidence.

중간 검증:

```bash
ssh toki@toki-labs.com 'set -euo pipefail
REVIEW_ROOT=/Users/toki/agent-work/iop-field-review
cd "$REVIEW_ROOT"
mkdir -p /tmp/iop-field-evidence build/dev-runtime/logs
CP_BIN=build/dev-runtime/bin/control-plane
EDGE_BIN=build/dev-runtime/bin/edge
NODE_BIN=build/dev-runtime/bin/iop-node
CP_CONFIG=build/dev-runtime/control-plane.yaml
EDGE_CONFIG=build/dev-runtime/edge.yaml
for pat in "control-plane.*build/dev-runtime/control-plane.yaml" "edge.*build/dev-runtime/edge.yaml" "iop-node.*build/dev-runtime/node-codex.yaml" "iop-node.*build/dev-runtime/node-onexplayer-lemonade.yaml"; do
  pgrep -f "$pat" | xargs -r kill
done
sleep 2
nohup "$CP_BIN" --config "$CP_CONFIG" serve > build/dev-runtime/logs/control-plane.log 2>&1 &
echo $! > build/dev-runtime/control-plane.pid
nohup "$EDGE_BIN" --config "$EDGE_CONFIG" serve > build/dev-runtime/logs/edge.log 2>&1 &
echo $! > build/dev-runtime/edge.pid
for name in node-codex node-onexplayer-lemonade; do
  cfg="build/dev-runtime/${name}.yaml"
  nohup "$NODE_BIN" --config "$cfg" serve > "build/dev-runtime/logs/${name}.log" 2>&1 &
  echo $! > "build/dev-runtime/${name}.pid"
done
'
ssh toki@toki-labs.com 'set -euo pipefail
REVIEW_ROOT=/Users/toki/agent-work/iop-field-review
GX10_HOST=192.168.0.91
ssh toki@"$GX10_HOST" "mkdir -p ~/iop-field-review/bin ~/iop-field-review/logs"
scp "$REVIEW_ROOT/build/dev-runtime/bin/iop-node-linux-arm64" toki@"$GX10_HOST":~/iop-field-review/bin/iop-node
scp "$REVIEW_ROOT/build/dev-runtime/node-gx10-vllm.yaml" toki@"$GX10_HOST":~/iop-field-review/node-gx10-vllm.yaml
ssh toki@"$GX10_HOST" "pkill -f \"iop-field-review/bin/iop-node.*node-gx10-vllm.yaml\" || true; chmod +x ~/iop-field-review/bin/iop-node; nohup ~/iop-field-review/bin/iop-node --config ~/iop-field-review/node-gx10-vllm.yaml serve > ~/iop-field-review/logs/node-gx10-vllm.log 2>&1 & echo \\\$! > ~/iop-field-review/node-gx10-vllm.pid"
'
ssh toki@toki-labs.com 'set -euo pipefail
EDGE_ID=edge-toki-labs-dev
REVIEW_ROOT=/Users/toki/agent-work/iop-field-review
cd "$REVIEW_ROOT"
for i in $(seq 1 120); do
  curl -fsS "http://127.0.0.1:18001/edges/${EDGE_ID}/status" > /tmp/iop-field-evidence/reconnect-before-status.json && grep -q "mac-codex-node" /tmp/iop-field-evidence/reconnect-before-status.json && grep -q "gx10-vllm-node" /tmp/iop-field-evidence/reconnect-before-status.json && grep -q "onexplayer-lemonade-node" /tmp/iop-field-evidence/reconnect-before-status.json && break || true
  sleep 1
done
grep -E "mac-codex-node|gx10-vllm-node|onexplayer-lemonade-node" /tmp/iop-field-evidence/reconnect-before-status.json
(lsof -nP -iTCP:18084 -sTCP:ESTABLISHED 2>/dev/null || ss -tn state established "( sport = :18084 )" 2>/dev/null || true) | tee /tmp/iop-field-evidence/reconnect-before-tcp.txt
BEFORE_PID="$(cat build/dev-runtime/edge.pid)"
kill "$BEFORE_PID"
for i in $(seq 1 20); do if ! kill -0 "$BEFORE_PID" 2>/dev/null; then break; fi; sleep 1; done
nohup build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml serve > build/dev-runtime/logs/edge.log 2>&1 &
AFTER_PID="$!"
echo "$AFTER_PID" > build/dev-runtime/edge.pid
printf "before_pid=%s after_pid=%s bootstrap_rerun=none\n" "$BEFORE_PID" "$AFTER_PID" | tee /tmp/iop-field-evidence/reconnect-pids.txt
for i in $(seq 1 120); do
  curl -fsS "http://127.0.0.1:18001/edges/${EDGE_ID}/status" > /tmp/iop-field-evidence/reconnect-after-status.json && grep -q "mac-codex-node" /tmp/iop-field-evidence/reconnect-after-status.json && grep -q "gx10-vllm-node" /tmp/iop-field-evidence/reconnect-after-status.json && grep -q "onexplayer-lemonade-node" /tmp/iop-field-evidence/reconnect-after-status.json && break || true
  sleep 1
done
grep -E "mac-codex-node|gx10-vllm-node|onexplayer-lemonade-node" /tmp/iop-field-evidence/reconnect-after-status.json
(lsof -nP -iTCP:18084 -sTCP:ESTABLISHED 2>/dev/null || ss -tn state established "( sport = :18084 )" 2>/dev/null || true) | tee /tmp/iop-field-evidence/reconnect-after-tcp.txt
REFRESH_ADDR="$(python3 - <<'"'"'PY'"'"'
from pathlib import Path
import re
s = Path("build/dev-runtime/edge.yaml").read_text()
m = re.search(r"(?ms)^refresh:\n(?:^[ \t]+.*\n)*?^[ \t]+listen:[ \t]*\"?([^\"\n]+)\"?", s)
print(m.group(1).strip() if m else "127.0.0.1:19093")
PY
)"
EDGE_PID_BEFORE="$(cat build/dev-runtime/edge.pid)"
build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config refresh --mode dry-run --addr "$REFRESH_ADDR" | tee /tmp/iop-field-evidence/refresh-dry-run.json
build/dev-runtime/bin/edge --config build/dev-runtime/edge.yaml config refresh --mode apply --addr "$REFRESH_ADDR" | tee /tmp/iop-field-evidence/refresh-apply.json
EDGE_PID_AFTER="$(cat build/dev-runtime/edge.pid)"
printf "edge_pid_before=%s edge_pid_after=%s\n" "$EDGE_PID_BEFORE" "$EDGE_PID_AFTER" | tee /tmp/iop-field-evidence/refresh-pid.txt
test "$EDGE_PID_BEFORE" = "$EDGE_PID_AFTER"
curl -fsS http://toki-labs.com:18083/healthz | tee /tmp/iop-field-evidence/refresh-healthz.txt
curl -fsS http://toki-labs.com:18083/v1/models | tee /tmp/iop-field-evidence/refresh-models.json
python3 - <<'"'"'PY'"'"' | tee /tmp/iop-field-evidence/refresh-concurrent-4.jsonl
import concurrent.futures, json, urllib.request
url = "http://toki-labs.com:18083/v1/chat/completions"
payload = {
  "model": "qwen3.6:35b",
  "messages": [{"role": "user", "content": "Reply with exactly IOP_FIELD_REFRESH_OK."}],
  "max_tokens": 32,
  "temperature": 0
}
def one(i):
    data = json.dumps(payload).encode()
    req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=300) as resp:
        body = json.loads(resp.read().decode())
    return {"index": i, "status": "ok", "id": body.get("id"), "model": body.get("model"), "usage": body.get("usage"), "content": body.get("choices", [{}])[0].get("message", {}).get("content", "")}
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as ex:
    for item in ex.map(one, range(4)):
        print(json.dumps(item, ensure_ascii=False))
PY
test "$(wc -l < /tmp/iop-field-evidence/refresh-concurrent-4.jsonl)" = "4"
'
```

Expected: command exits 0; before/after status contains 3 node ids; reconnect pids record `bootstrap_rerun=none`; refresh dry-run/apply JSON exists; Edge PID before/after refresh is identical; health/models succeeds; `refresh-concurrent-4.jsonl` has exactly 4 successful JSON lines.

## 수정 파일 요약

| 파일/경로 | 항목 |
|------|------|
| `/Users/toki/agent-work/iop-field-review/**` | REVIEW_REVIEW_TEST-1, REVIEW_REVIEW_TEST-2 |
| `/tmp/iop-field-evidence/**` | REVIEW_REVIEW_TEST-1, REVIEW_REVIEW_TEST-2 |
| `CODE_REVIEW-cloud-G08.md` | REVIEW_REVIEW_TEST-1, REVIEW_REVIEW_TEST-2 |

## 최종 검증

```bash
git diff --check
```

Expected: no output.

```bash
rg --sort path -n 'Control Plane status에서 `edge-toki-labs`|build/dev-runtime/iop-edge|build/bin/iop-edge|\./iop-edge --config build/dev-runtime/edge.yaml' docs/edge-local-dev-guide.md agent-test/local/edge-smoke.md
```

Expected: no matches. If `rg` exits 1 with no matches, record that as pass.

```bash
ssh toki@toki-labs.com 'test -s /tmp/iop-field-evidence/review-config-refresh-help.txt && test -s /tmp/iop-field-evidence/reconnect-before-status.json && test -s /tmp/iop-field-evidence/reconnect-after-status.json && test -s /tmp/iop-field-evidence/reconnect-after-tcp.txt && test -s /tmp/iop-field-evidence/reconnect-pids.txt && test -s /tmp/iop-field-evidence/refresh-apply.json && test -s /tmp/iop-field-evidence/refresh-pid.txt && test -s /tmp/iop-field-evidence/refresh-concurrent-4.jsonl && test "$(wc -l < /tmp/iop-field-evidence/refresh-concurrent-4.jsonl)" = "4"'
```

Expected: command exits 0.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
