# Milestone: Multi-Edge 운영

## 위치

- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/control-plane-portal-ops/PHASE.md`

## 목표

여러 Edge group을 연결하고 운영하는 fleet-level 기능을 구축한다.
Control Plane은 Edge를 제어하기 쉽게 연결하는 레이어이며, Edge의 설정과 실질 상태 원본은 Edge가 소유한다.

## 상태

[완료]

## 구현 잠금

- 상태: 해제
- 결정 필요: 없음 (아래 결정 기록)
  - [x] Multi-Edge 1차 범위를 observe-only로 둘지, fleet-wide 명령까지 포함할지 결정한다. 결정: 관찰은 Edge 연결/health 확인 수준으로 제한하고, 1차 범위는 multi-edge 운영이 실제 가능하도록 fleet-wide 명령과 제어를 포함한다.
  - [x] Control Plane과 Edge 사이의 상태 소유권과 aggregation 깊이를 결정한다. 결정: Edge 설정, Node registry, runtime/automation 상태의 원본은 Edge가 소유한다. Control Plane은 연결된 Edge를 제어하기 위한 연결/health, capability 요약, 명령 요청/결과, audit에 필요한 최소 운영 기록만 가진다. Edge는 다른 Control Plane으로 옮길 수 있어야 하며 Control Plane에 실질 데이터를 묶지 않는다.
  - [x] OTO/build-deploy domain agent 상태를 fleet 화면의 1차 범위에 포함할지 결정한다. 결정: OTO/build-deploy는 1차 fleet 운영 capability로 포함한다. 단, Control Plane에는 Edge-owned capability/status/command summary만 노출하고, 실제 artifact/log/state 원본은 Edge 또는 해당 domain agent가 소유한다.

## 범위

- 여러 Edge group 등록/연결/health 표시
- Edge가 제공하는 runtime/automation capability와 운영 가능 상태 요약
- Edge 단위 실행/명령 결과와 event relay
- Edge 단위 작업 실행과 제어
- OTO 같은 domain agent의 build/deploy capability, ready/busy/error 상태, 명령 요청/진행/결과 요약 포함
- fleet-wide 명령과 운영 리포트

## 기능

### Epic: [fleet-ops-boundary] Fleet Operations Boundary

- [x] [native-fleet] Multi-edge 운영 명령과 이벤트 relay는 IOP native protocol을 기준으로 설계한다.
- [x] [edge-status-view] Control Plane은 여러 Edge 상태를 구분해 조회하고 표시할 수 있다. 검증: 두 개 이상의 Edge 상태가 구분되는 조회/표시 경로를 확인한다.
- [x] [history-agent-state] Edge별 실행/명령 결과와 domain agent capability/status/command summary가 운영 화면에서 구분된다.
- [x] [openai-routing] OpenAI-compatible 표면은 특정 Edge/adapter로 라우팅되는 inference 호환 경로로 제한한다.
- [x] [a2a-routing] A2A 표면은 특정 Edge/adapter로 위임되는 agent task 경로로 제한한다.
- [x] [edge-ownership] Edge는 설정, Node registry, 로컬 런타임 상태의 원본 소유권을 유지하고, Control Plane은 이동 가능한 제어 attachment로만 동작한다.

## 완료 리뷰

- 상태: 승인됨
- 요청일: 2026-06-05
- 완료 근거: 모든 기능 Task와 Task 안에 명시된 검증이 충족된 것으로 보인다. `history-agent-state`는 Edge별 command audit, domain agent active command summary, operations history가 서로 섞이지 않는 widget/backend 검증으로 보강되었다.
- 리뷰 필요:
  - [x] 사용자가 완료 결과를 확인했다
  - [x] archive 이동을 승인했다
- 리뷰 코멘트: 사용자 승인에 따라 Multi-Edge 운영 마일스톤을 `[완료]`로 전환하고 archive 이동 대상으로 확정했다.

## 범위 제외

- Control Plane이 매 요청마다 Node를 직접 할당하는 중앙 스케줄러 역할
- Control Plane이 Edge 설정, Node registry, runtime/automation 상태의 실질 원본을 소유하는 구조
- Control Plane이 OTO/build-deploy artifact 저장소, 상세 log, domain-specific lifecycle 원본을 소유하는 구조
- OpenAI-compatible API 또는 A2A API를 multi-edge 운영 제어 기본 프로토콜로 사용
- Edge federation 상세 설계를 근거 없이 선확정

## 작업 컨텍스트

- 관련 경로: `apps/control-plane`, `apps/client`, `apps/edge`, `README.md`
- 표준선(선택): Edge는 설정, 로컬 런타임 상태, Node registry의 원본 소유권을 유지하고, Control Plane은 연결/health 확인을 기반으로 fleet-wide 명령과 제어를 조율한다. Control Plane 교체나 이전은 Edge 실질 데이터 이전을 요구하지 않아야 한다.
- 선행 작업: Control Plane과 Client, 정책/이력/감사
- 후속 작업: 없음
- 결정됨: Multi-Edge 1차 범위는 observe-only가 아니라 fleet-wide 운영 중심으로 둔다. 관찰은 Edge 접속/health 확인 수준으로 제한한다.
- 결정됨: Control Plane은 Edge 실질 데이터를 소유하지 않는 제어 레이어로 둔다. Aggregation은 제어에 필요한 연결/health, capability 요약, 명령 요청/결과, audit record 수준으로 제한한다.
- 결정됨: OTO/build-deploy domain agent는 1차 fleet 운영 capability에 포함한다. Control Plane은 Edge-owned capability/status/command summary만 다루고 artifact/log/state 원본은 소유하지 않는다.
- 완료 근거: [openai-routing] `apps/edge/internal/openai/server.go`는 Edge-local `SubmitRun`/`OllamaAPI`로만 `adapter + target` inference 요청을 변환하며 Control Plane 운영 제어 표면으로 쓰지 않는다. 검증: `go test ./apps/edge/internal/openai` 통과.
- 완료 근거: [a2a-routing] `apps/edge/internal/input/a2a/server.go`는 Edge-local `SubmitRun`/`CancelRun`을 통해 특정 `adapter + target` agent task 위임만 처리한다. 검증: `go test ./apps/edge/internal/input/a2a` 통과.
- 완료 근거: [native-fleet] `proto/iop/control.proto`에 native command 요청/응답/이벤트 relay와 capability/status 요약 메시지를 추가하고, Control Plane과 Edge의 parser map을 갱신했다. 검증: `make proto proto-dart` 및 `go test ./apps/control-plane/internal/wire` 통과.
- 완료 근거: [edge-ownership] Control Plane native contract/registry에 Edge config, Node registry, agent lifecycle detail 원본이 노출되지 않도록 descriptor 및 reflect 기반 소유권 가드 테스트(`TestProtoOwnershipGuard`, `TestControlPlaneRegistryOwnershipGuard`)를 추가했다. 검증: `go test ./apps/control-plane/internal/wire` 통과.
- 완료 근거: [edge-status-view] `apps/client/test/widget_test.dart`에서 두 Edge의 fleet status가 선택에 따라 `Edge Alpha`/`Edge Beta`, `edge-a`/`edge-b`, connected/disconnected, health 값을 구분해 표시되는 경로를 고정했다. 검증: `cd apps/client && flutter test test/widget_test.dart` 통과.
- 완료 근거: [history-agent-state] `apps/control-plane/cmd/control-plane/main_test.go`와 `apps/client/test/widget_test.dart`에서 Edge별 command audit, domain agent capability/status/active command summary, operations history가 `edge-a`/`edge-b` 선택에 따라 분리 표시되고 stale operations가 즉시 제거되는 경로를 고정했다. 검증: `go test ./apps/control-plane/cmd/control-plane -run 'TestFleetStatusHTTPHandlerCombinesConnectionAndCapabilities|TestEdgeOperationsHTTPHandlerListsAudit' -count=1`, `cd apps/client && flutter test test/widget_test.dart` 통과.
