<!-- task=m-multi-edge-operations/02+01_edge_fleet_ops review=0 tag=API -->
# Code Review - Edge Fleet Operations

## Review Scope

- `apps/edge/internal/controlplane/connector.go`
- `apps/edge/internal/service/service.go`
- Edge connector/service tests

## Dependency Check

- [x] `agent-task/m-multi-edge-operations/01_native_contract/complete.log` 확인

## Reviewer Checklist

- [ ] command 처리가 Edge-local service 책임으로 남아 있다.
- [ ] Control Plane 연결/재연결이 Edge 설정 원본을 변경하지 않는다.
- [ ] OTO/build-deploy 정보는 summary 수준이다.
- [ ] unsupported/busy/error command 응답이 명확하다.
- [ ] event relay가 연결 실패/재연결 상황에서 안전하다.
- [ ] secret/config detail이 status response로 새지 않는다.

## Verification Result

- [x] `go test ./apps/edge/internal/service ./apps/edge/internal/controlplane`
- [x] 필요한 경우 `go test ./apps/edge/...`

## User Review

검토 기본값: 이 리뷰는 사용자가 명시적으로 보류하지 않으면 구현자가 자체 검증 후 완료 처리한다.

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail - `agent.command`가 실제 node command/run/cancel 경로를 호출하지 않고 synthetic success를 반환한다.
  - completeness: Fail - 계획의 command 처리, busy/error 상태, summary-only status 요구가 모두 충족되지 않았다.
  - test coverage: Fail - 현재 테스트는 node transport를 사용하지 않는 fake 성공 경로를 통과시켜 핵심 회귀를 잡지 못한다.
  - API contract: Fail - status response가 `NodeConfigPayload`를 그대로 포함해 native summary 계약과 secret/config 비노출 체크포인트와 충돌한다.
  - code quality: Warn - `git diff --check`가 trailing whitespace와 EOF blank line을 보고한다.
  - plan deviation: Fail - plan은 Edge-owned command result/progress relay를 요구했지만 구현은 command 수행을 시뮬레이션한다.
  - verification trust: Warn - `go test -count=1 ./apps/edge/...`는 통과했지만 Required 동작을 검증하지 않는 테스트라 충분한 신뢰 증거가 아니다.
- 발견된 문제:
  - Required: `apps/edge/internal/service/service.go:654`의 `agent.command` 분기는 `ResolveNode` 뒤에 `entry.Client.Send`, `toki.SendRequestTyped`, `SubmitRun`, `CancelRun`, `TerminateSession`, `Capabilities` 등 실제 Edge-local service/transport 작업을 전혀 호출하지 않고 `time.Sleep` 후 `completed`를 반환한다. `apps/edge/internal/service/service_test.go:501` 테스트도 `Client`가 없는 `NodeEntry`로 성공을 기대해 이 결함을 고정한다. `agent.command`는 지원하는 operation/parameters를 기존 service command/run/cancel 경로에 매핑하고 downstream ACK/error를 response로 반영하거나, 아직 구현하지 않은 command는 `unsupported`로 반환해야 한다.
  - Required: `apps/edge/internal/service/service.go:550`의 capability summary는 연결된 OTO가 `LifecycleState: "deploying"`이어도 `build-deploy` capability를 항상 `status: "ready"`로 반환한다. `apps/edge/internal/service/service_test.go:395`는 non-ready 상태 fixture를 만들고도 `ready`를 기대해 busy/error 상태 요구를 검증하지 못한다. lifecycle state를 ready/busy/error summary로 변환하고, command가 busy/error를 명확히 반환하는 회귀 테스트를 추가해야 한다.
  - Required: `apps/edge/internal/controlplane/connector.go:366`에서 status response node snapshot에 `Config: s.Config`를 그대로 복사하고, `apps/edge/internal/controlplane/connector_test.go:731`은 이 동작을 요구한다. `NodeConfigPayload`는 `apps/edge/internal/node/mapper.go:16`, `apps/edge/internal/node/mapper.go:69` 기준 workspace root, adapter endpoint, CLI command/args/env를 포함할 수 있으므로 review checklist의 "secret/config detail이 status response로 새지 않는다"와 summary-only 계약을 깨뜨린다. Control Plane status에는 summary 필드만 남기고 full config를 제거하거나 명시적으로 sanitize해야 한다.
  - Nit: `git diff --check`가 `apps/edge/internal/controlplane/connector_test.go:818`, `apps/edge/internal/service/service.go:552` 등 trailing whitespace와 `proto/iop/control.proto:139` EOF blank line을 보고한다. 후속 구현에서 `gofmt`와 `git diff --check`로 정리한다.
- 다음 단계: FAIL follow-up으로 `PLAN-cloud-G06.md`와 `CODE_REVIEW-cloud-G06.md`를 작성한다.

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

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-cloud-G05.md`를 `code_review_cloud_G05_0.log`로 아카이브한다.
- [x] active `PLAN-cloud-G05.md`를 `plan_cloud_G05_0.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리를 archive로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G06.md`와 `CODE_REVIEW-cloud-G06.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가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
