diff --git a/README.md b/README.md index 306ceb3..7a8201e 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ target = codex-local ## 아키텍처 -IOP는 Control Plane이 Edge를 통해 시스템을 제어하고, Edge가 자신의 로컬 실행 그룹을 운영하는 구조를 지향한다. +IOP는 Control Plane이 Edge를 통해 시스템을 제어하고, Edge가 자신의 로컬 실행 그룹을 운영하는 구조를 지향한다. Control Plane은 Edge를 제어하기 쉽게 연결하는 레이어이며, Edge 설정과 실질 상태의 원본을 소유하지 않는다. ```text Control Plane @@ -72,17 +72,17 @@ Control Plane └─ OTO Agent 2 ``` -Control Plane은 Node에 직접 연결하지 않는다. 전체 시스템 제어는 Edge를 통해 이뤄지고, Edge는 자신이 관리하는 Node와 로컬 런타임 상태의 원본을 가진다. +Control Plane은 Node에 직접 연결하지 않는다. 전체 시스템 제어는 Edge를 통해 이뤄지고, Edge는 자신이 관리하는 Node 설정, Node registry, 로컬 런타임 상태의 원본을 가진다. 여러 Control Plane이 있더라도 Edge는 실질 데이터 이전 없이 다른 Control Plane으로 연결 대상을 옮길 수 있어야 한다. 핵심 문장은 다음과 같다. -> Control Plane은 Edge를 통해 시스템을 제어하고, Edge는 자신의 로컬 런타임 상태를 소유하고 운영한다. +> Control Plane은 Edge를 통해 시스템을 제어하고, Edge는 자신의 설정과 로컬 런타임 상태를 소유하고 운영한다. -운영 표면은 두 층으로 나눈다. `iop-edge` CLI는 Control Plane 없이도 bootstrap, local config, 진단, node 등록 command 발급, smoke, 단일 Edge 유지보수를 할 수 있는 field/fallback interface로 유지한다. Control Plane은 여러 Edge를 상시 관찰하고 명령, 정책, 감사, 팀 운영 UX를 제공하는 기본 운영면으로 확장한다. 둘 다 필요한 작업은 Edge가 소유한 shared operation으로 분류하고, CLI와 Control Plane이 각각 구현을 복제하지 않는다. +운영 표면은 두 층으로 나눈다. `iop-edge` CLI는 Control Plane 없이도 bootstrap, local config, 진단, node 등록 command 발급, smoke, 단일 Edge 유지보수를 할 수 있는 field/fallback interface로 유지한다. Control Plane은 여러 Edge의 연결/health를 확인하고 fleet-wide 명령, 정책, 감사, 팀 운영 UX를 제공하는 기본 운영면으로 확장한다. 둘 다 필요한 작업은 Edge가 소유한 shared operation으로 분류하고, CLI와 Control Plane이 각각 구현을 복제하지 않는다. ### 제어면(Control Plane) -Control Plane은 자체 서버와 프론트 페이지를 가진 중앙 관리 계층이다. +Control Plane은 자체 서버와 Client 표면을 통해 Edge를 제어하는 운영 계층이다. Edge 데이터의 canonical store가 아니라, 연결된 Edge에 제어 요청을 보내고 결과를 보기 쉽게 만드는 attachable layer다. 주요 책임은 다음과 같다. @@ -91,7 +91,7 @@ Control Plane은 자체 서버와 프론트 페이지를 가진 중앙 관리 - Edge 설정 변경 - Edge에 명령 전달 - Edge 이벤트 수신 -- 전체 시스템 관찰 +- Edge 연결/health와 제어 결과 관찰 - Runtime 영역과 Automation 영역을 나눠 보여주는 운영 화면 제공 Control Plane과 Edge는 소켓 기반 연결을 사용하고, 이벤트, 상태, 명령 결과를 실시간으로 주고받는 구조를 지향한다. @@ -102,6 +102,7 @@ Control Plane은 전통적인 Kubernetes식 중앙 스케줄러가 아니다. - Node 직접 스케줄링 - Edge 내부 DB 대체 - 모든 런타임 상태의 단일 원본화 +- Edge 설정, Node registry, runtime/automation 상태의 원본 저장소 역할 - 매 요청마다 Node 할당 판단 ### Edge @@ -126,11 +127,11 @@ Edge의 핵심 역할은 다음과 같다. - Execution history aggregation - Event aggregation -Edge는 자신의 데이터를 자체적으로 가진다. Control Plane은 Edge의 데이터를 조회하고 조정하지만, 런타임 데이터의 원본은 Edge다. +Edge는 자신의 데이터를 자체적으로 가진다. Control Plane은 Edge의 데이터를 조회하고 제어 요청을 전달하지만, 설정과 런타임 데이터의 원본은 Edge다. 현재 edge 내에는 edge-local ops console이 있다. ops console의 `/` 명령은 `apps/edge/internal/service`를 호출하는 얇은 어댑터이며, 향후 HTTP/API handler도 같은 service를 호출하는 방향이다. HTTP/API를 central/remote management surface로, ops console을 edge-local diagnostic surface로 구분한다. 실행 이벤트와 node lifecycle 이벤트는 `apps/edge/internal/events` bus를 통해 fanout한다. -새 command나 운영 기능은 먼저 `Edge-local 필수`, `Control Plane 기본`, `shared operation` 중 하나로 분류한다. Edge-local 필수 범위에는 bootstrap/config/env/setup/node register/nodes list/smoke 같은 Control Plane 없는 field 경로가 들어가고, Control Plane 기본 범위에는 multi-edge 관찰, fleet-wide command, 정책/감사, 반복 운영 리포트가 들어간다. +새 command나 운영 기능은 먼저 `Edge-local 필수`, `Control Plane 기본`, `shared operation` 중 하나로 분류한다. Edge-local 필수 범위에는 bootstrap/config/env/setup/node register/nodes list/smoke 같은 Control Plane 없는 field 경로가 들어가고, Control Plane 기본 범위에는 multi-edge 연결/health 확인, fleet-wide command, 정책/감사, 반복 운영 리포트가 들어간다. ### Node diff --git a/agent-ops/rules/project/domain/control-plane/rules.md b/agent-ops/rules/project/domain/control-plane/rules.md index 4817fb2..32da936 100644 --- a/agent-ops/rules/project/domain/control-plane/rules.md +++ b/agent-ops/rules/project/domain/control-plane/rules.md @@ -1,14 +1,14 @@ --- domain: control-plane last_rule_review_commit: 49872ae120627c47175194e837d90f8915d67397 -last_rule_updated_at: 2026-06-01 +last_rule_updated_at: 2026-06-03 --- # control-plane ## 목적 / 책임 -여러 Edge를 관찰하고 운영 제어할 중앙 제어면 영역이다. 현재는 health/readiness와 Edge registry 조회 HTTP, 환경별 설정 로딩, Client proto-socket WebSocket, Edge proto-socket TCP 연결 baseline을 제공하며, Node 직접 연결이나 직접 스케줄링은 책임으로 삼지 않는다. +여러 Edge를 연결하고 운영 제어할 제어면 영역이다. Control Plane은 Edge를 제어하기 쉽게 만드는 attachable layer이며, Edge의 실질 설정과 상태 원본을 소유하지 않는다. 현재는 health/readiness와 Edge registry 조회 HTTP, 환경별 설정 로딩, Client proto-socket WebSocket, Edge proto-socket TCP 연결 baseline을 제공하며, Node 직접 연결이나 직접 스케줄링은 책임으로 삼지 않는다. ## 포함 경로 @@ -38,34 +38,37 @@ last_rule_updated_at: 2026-06-01 - `wire.Endpoint` — reserved wire endpoint 설정 타입 - `wire.ClientServer` — `/client` WebSocket proto-socket hello 요청을 처리하는 서버 구현 - `wire.EdgeServer` — Edge outbound TCP proto-socket 연결을 수락하고 hello/status/event 흐름을 처리하는 서버 구현 -- `wire.EdgeRegistry` — Edge connection state와 최근 node lifecycle event를 보관하는 in-memory registry +- `wire.EdgeRegistry` — Edge connection view와 최근 node lifecycle event relay를 보관하는 in-memory registry - `wire.EdgeParserMap()` — Control Plane-Edge wire message parser map - `wire.EdgeServer.RequestStatus()` — 연결된 Edge에 `EdgeStatusRequest`를 보내 Edge-owned node snapshot을 조회하는 helper ## 유지할 패턴 - Control Plane은 Edge를 통해 시스템을 관찰/제어한다. Node를 직접 등록하거나 직접 스케줄링하는 active contract를 만들지 않는다. +- Control Plane은 Edge의 설정, Node registry, runtime/automation 상태의 canonical store가 아니다. Control Plane이 소유할 수 있는 것은 연결 view, 제어 요청/결과, audit에 필요한 최소 운영 기록으로 제한한다. +- Edge는 다른 Control Plane으로 연결 대상을 옮길 수 있어야 한다. Control Plane 교체나 이전이 Edge 실질 데이터 migration을 요구하는 구조를 만들지 않는다. - Control Plane은 상시 운영, multi-edge 관찰/명령, 정책/감사 UX의 기본 운영면으로 확장한다. Edge-local bootstrap, config, 진단, 단일 Edge 유지보수 fallback을 대체하거나 제거하는 전제로 설계하지 않는다. - Control Plane-Edge wire protocol은 Edge가 소유한 operation contract를 원격 운영면으로 소비하는 형태로 설계한다. Edge CLI와 같은 행위를 노출해야 하면 Edge 쪽 표면 중립 service/operation boundary로 수렴시킨다. - `net/http`는 health/readiness와 단순 조회성 status endpoint에 우선 사용하고, IOP 고유 양방향 운영 통신은 proto-socket 기반 wire protocol로 확장한다. - 브라우저/앱 경계는 WebSocket/WSS proto-socket을 사용할 수 있다. Edge-Node TCP transport 기준을 이 경계에 억지로 적용하지 않는다. - Control Plane-Edge native wire는 Edge가 outbound로 연결하는 TCP proto-socket 경계로 둔다. Client WebSocket listener와 Edge TCP listener를 혼동하지 않는다. -- Edge registry는 현재 in-memory 관찰 baseline이다. durable history, audit, 정책 저장소를 이 registry에 섞지 않는다. -- Edge status 조회는 Edge가 보고한 `EdgeStatusResponse`를 관찰한다. Control Plane에서 Node address, token, transport internals를 직접 소유하지 않는다. +- Edge registry는 현재 in-memory connection/control view이다. durable history, audit, 정책 저장소를 이 registry에 섞지 않는다. +- Edge status 조회는 Edge가 보고한 `EdgeStatusResponse`를 관찰한다. Control Plane에서 Node address, token, transport internals, Edge 설정 원본을 직접 소유하지 않는다. - `ScheduleRequest`/`ScheduleResponse`는 legacy placeholder로만 취급하고, 새 orchestration 계약은 Edge-owned runtime state를 우회하지 않도록 다시 설계한다. - Control Plane 설정에 실제 환경값, credential, private endpoint를 tracked 문서에 쓰지 않는다. 환경별 값은 private rule 라우팅을 따른다. - proto 계약을 바꾸면 `proto/iop/*.proto`를 먼저 수정하고 Go 생성물을 명령으로 갱신한다. ## 다른 도메인과의 경계 -- **edge**: Edge는 로컬 실행 그룹 상태와 Node registry를 소유한다. Control Plane은 Edge를 통해 상태 조회, 설정 변경, 명령 전달, 이벤트 수신을 확장한다. Control Plane 없는 bootstrap/local/field/진단 fallback은 `iop-edge` command 표면에 남긴다. -- **client**: Client는 Control Plane의 HTTP/WS 표면을 소비하는 UI/UX와 Dart wire wrapper를 소유한다. Control Plane은 server endpoint와 Edge connection registry를 소유한다. +- **edge**: Edge는 설정, 로컬 실행 그룹 상태와 Node registry 원본을 소유한다. Control Plane은 Edge를 통해 상태 조회, 설정 변경 요청, 명령 전달, 이벤트 수신을 확장한다. Control Plane 없는 bootstrap/local/field/진단 fallback은 `iop-edge` command 표면에 남긴다. +- **client**: Client는 Control Plane의 HTTP/WS 표면을 소비하는 UI/UX와 Dart wire wrapper를 소유한다. Control Plane은 server endpoint와 Edge connection/control view를 소유한다. - **platform-common**: protobuf 원본, 생성물, 공통 설정/관측성 helper는 platform-common 계약을 따른다. - **testing**: Control Plane command, wire endpoint, bootstrap/enrollment 사용자 흐름을 바꾸면 testing domain rule의 검증 기준을 따른다. ## 금지 사항 - Control Plane에서 Node를 직접 연결하거나 직접 스케줄링하는 경로를 제품 기본 계약으로 만들지 않는다. +- Edge 설정, Node registry, runtime/automation 상태의 원본 저장소를 Control Plane에 만들지 않는다. - Edge-local registry, run dispatch, stream relay 구현을 Control Plane으로 복제하지 않는다. - Edge가 보고하지 않은 Node address/token/scheduling 필드를 Control Plane status API에 만들지 않는다. - Control Plane 도입만을 이유로 Edge-local CLI bootstrap/config/진단 fallback을 제품 기본 계약에서 제외하거나 제거하지 않는다. 축소는 별도 roadmap 결정과 대체 fallback 기준이 있을 때만 다룬다. diff --git a/agent-ops/rules/project/domain/edge/rules.md b/agent-ops/rules/project/domain/edge/rules.md index 676ad52..e5c67bb 100644 --- a/agent-ops/rules/project/domain/edge/rules.md +++ b/agent-ops/rules/project/domain/edge/rules.md @@ -1,14 +1,14 @@ --- domain: edge last_rule_review_commit: 49872ae120627c47175194e837d90f8915d67397 -last_rule_updated_at: 2026-06-01 +last_rule_updated_at: 2026-06-03 --- # edge ## 목적 / 책임 -여러 Node를 하나의 로컬 실행 그룹으로 묶는 백엔드 실행 그룹 컨트롤러 영역이다. node 연결을 수락하고 token 기반 등록을 검증한 뒤 adapter/runtime 설정을 내려주며, `iop-edge` command 중심의 local/field 운영 UX, ops console, OpenAI-compatible HTTP, A2A JSON-RPC, Control Plane outbound connector를 내부 Edge-owned operation으로 수렴시킨다. +여러 Node를 하나의 로컬 실행 그룹으로 묶는 백엔드 실행 그룹 컨트롤러 영역이다. node 연결을 수락하고 token 기반 등록을 검증한 뒤 adapter/runtime 설정을 내려주며, `iop-edge` command 중심의 local/field 운영 UX, ops console, OpenAI-compatible HTTP, A2A JSON-RPC, Control Plane outbound connector를 내부 Edge-owned operation으로 수렴시킨다. Edge는 자신의 설정, Node registry, runtime/automation 상태의 원본 소유자다. ## 포함 경로 @@ -67,6 +67,7 @@ last_rule_updated_at: 2026-06-01 - edge는 사전 등록된 node 정의를 검증하고 연결 상태를 registry에 반영하는 역할을 먼저 안정화한다. - edge는 단순 gateway가 아니라 Node registry, adapter/profile configuration, routing, stream relay의 소유자다. +- edge는 `edge.yaml`, node 정의, adapter/runtime 설정, 로컬 runtime/automation 상태의 canonical owner다. Control Plane 연결 대상이 바뀌어도 Edge 실질 데이터 migration을 요구하지 않는 구조를 유지한다. - 공식 local/field 운영 UX는 `iop-edge` command 표면에 모은다. repo helper script나 README 절차를 공식 사용자 경로로 승격하지 않는다. - `iop-edge` command 표면은 bootstrap, bundle-local config, env/config 진단, node 등록 command 발급, smoke, Control Plane 없는 단일 Edge 유지보수 범위로 유지한다. 후속 specialized agent enrollment command도 같은 local/field fallback 원칙을 따른다. 상시 multi-edge 운영 UI/API 역할을 CLI에 확대하지 않는다. - `config init`은 bundle-local `edge.yaml` template을 만들고, `env`는 서버를 기동하지 않고 effective environment를 설명해야 한다. @@ -83,7 +84,7 @@ last_rule_updated_at: 2026-06-01 - OpenAI/Ollama passthrough성 옵션은 입력 표면에서 명시적으로 변환하고, node adapter의 Ollama 실행 계약을 우회하지 않는다. - run/node event fanout은 `events.Bus`를 통해 수행하고, transport handler에서 console/HTTP 표면으로 직접 출력하거나 응답하지 않는다. - 입력 서버 lifecycle은 `input.Manager`가 소유하며, bootstrap runtime이 transport server와 함께 시작/종료한다. -- Control Plane connector는 disabled 설정 또는 빈 `wire_addr`에서 no-op이어야 한다. 연결 재시도와 stop은 Edge serve lifecycle에 묶는다. +- Control Plane connector는 disabled 설정 또는 빈 `wire_addr`에서 no-op이어야 한다. 연결 재시도와 stop은 Edge serve lifecycle에 묶으며, Control Plane attachment 변경이 Edge-owned 설정/상태의 소유권을 바꾸지 않는다. - Control Plane status 응답은 `service.Service`의 `ListNodeSnapshots()` 같은 Edge-owned 표면에서 만든다. connector가 registry나 transport internals를 직접 읽어 제품 계약을 만들지 않는다. - Control Plane node lifecycle event relay는 `events.Bus` 구독으로 수행하고, event metadata에는 필요한 Edge identity만 보강한다. - CLI, ops console, HTTP/A2A 입력 표면, Control Plane wire connector가 같은 Edge operation을 노출할 때는 `service.Service` 같은 표면 중립 application service로 수렴시킨다. registry 변경, run dispatch, command request 로직을 표면별로 복제하지 않는다. @@ -94,7 +95,7 @@ last_rule_updated_at: 2026-06-01 - **node**: edge는 node 내부 adapter를 직접 실행하지 않는다. edge는 사전 등록 정보와 연결 registry를 기반으로 요청을 보낼 대상과 실행 설정을 관리하고, TCP/protobuf로 `RunRequest`/`CancelRequest`/`NodeCommandRequest`를 보낸다. - **platform-common**: edge 설정, metrics, protobuf 타입은 platform-common 계약을 따른다. - **external input surfaces**: OpenAI-compatible HTTP와 A2A JSON-RPC는 edge inbound adapter이며, 내부 transport/protobuf 경계를 대체하지 않는다. -- **control-plane**: control-plane은 Edge를 통해 시스템을 제어한다. Edge domain은 outbound connector와 Edge-owned status/event 응답을 소유하고, control-plane domain은 server endpoint와 Edge registry view를 소유한다. Control Plane 없는 bootstrap/local/field/진단 fallback은 `iop-edge` command 표면에 남긴다. +- **control-plane**: control-plane은 Edge를 통해 시스템을 제어한다. Edge domain은 outbound connector와 Edge-owned status/event/command 응답을 소유하고, control-plane domain은 server endpoint와 Edge connection/control view를 소유한다. Control Plane 없는 bootstrap/local/field/진단 fallback은 `iop-edge` command 표면에 남긴다. ## 금지 사항 @@ -102,6 +103,7 @@ last_rule_updated_at: 2026-06-01 - OpenAI-compatible HTTP API를 추가할 때 내부 TCP/protobuf 경계를 우회하지 않는다. - A2A/OpenAI/console 입력 표면에서 registry client에 직접 `RunRequest`를 조립·전송하지 않는다. 공유 로직은 `service.Service`에 둔다. - Control Plane 구현 전이라도 Node를 Control Plane에 직접 연결하는 경로를 edge 도메인에 추가하지 않는다. +- Control Plane을 Edge 설정, Node registry, runtime/automation 상태의 원본 저장소로 전제하지 않는다. - Control Plane connector에서 Node token, Node address, transport client 내부 상태를 Control Plane status 계약으로 노출하지 않는다. - Control Plane 도입만을 이유로 `iop-edge config`, `env`, `node register`, `nodes list`, `smoke`, `setup` 같은 local/field fallback command 경로를 제거하거나 제품 기본 계약에서 제외하지 않는다. 축소는 별도 roadmap 결정과 대체 fallback 기준이 있을 때만 다룬다. - `node register`와 bootstrap UX에 named environment parameter 조합을 기본 사용자 경로로 노출하지 않는다. diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index d5c5881..32d324f 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -10,14 +10,14 @@ - IOP(Inference Operations Platform)는 Control Plane - Edge - Node 계층 구조를 기반으로 모델 서빙과 CLI Agent/Automation 실행을 함께 다루는 실행 오케스트레이션 모노레포이다. 핵심 서비스는 Go이고 운영 client는 Flutter/Dart이다. - 내부 실행 개념은 model 중심이 아니라 `adapter + target` 중심으로 정리한다. 외부 OpenAI-compatible 경계나 외부 CLI 인자에서는 호환성을 위해 `model` 표현이 남을 수 있다. - 현재 구현 중심은 `apps/node`와 `apps/edge`의 Edge-Node 실행 경로, `apps/control-plane`의 Control Plane-Edge/Client wire baseline, `apps/client`의 Flutter 운영 UI, `iop-edge` command 중심의 local/field 운영 UX, OpenAI-compatible/A2A 입력 표면, CLI adapter logical session/runtime이다. -- `apps/control-plane`은 health/readiness HTTP, Client proto-socket WebSocket, Edge proto-socket TCP 연결 baseline을 가진 중앙 제어면이다. +- `apps/control-plane`은 health/readiness HTTP, Client proto-socket WebSocket, Edge proto-socket TCP 연결 baseline을 가진 제어 레이어이다. Edge의 실질 설정과 상태 원본을 소유하지 않고, 연결된 Edge를 제어하기 쉽게 만든다. - `apps/worker`는 CLI placeholder 수준이므로 본격 구현 전 별도 domain rule을 만들거나 갱신한다. ## 주요 구조 - `apps/node/` — Edge에 연결되는 실행자. 런타임 라우팅, adapter execution, CLI/model runtime 실행, 현재 단계의 로컬 실행 이력 저장을 담당한다. - `apps/edge/` — 여러 Node를 묶는 백엔드 실행 그룹 컨트롤러. token 기반 등록, node registry, node 설정 전달, routing, stream relay, ops console, OpenAI-compatible/A2A 입력 표면을 담당한다. -- `apps/control-plane/` — 여러 Edge를 연결하고 상태 조회/설정 변경/명령 전달/이벤트 수신/운영 제어 API 제공을 담당할 Go 기반 중앙 관리 서버이다. +- `apps/control-plane/` — 여러 Edge를 연결하고 상태 조회, 설정 변경 요청, 명령 전달, 이벤트 수신, 운영 제어 API 제공을 담당할 Go 기반 제어 서버이다. Edge 데이터의 canonical store가 아니다. - `apps/client/` — Control Plane을 통해 Edge/Node 운영 상태를 보여주는 Flutter client이다. - `apps/worker/` — 비동기 작업 처리 예정 영역이다. 현재 placeholder이다. - `packages/go/` — 설정, 인증, 이벤트 helper, host setup, 정책, 메타데이터, 작업, 관측성, 버전 등 Go 공통 패키지이다. @@ -51,9 +51,9 @@ - 기존 hexagonal 구조를 유지한다. 특히 `apps/node/internal/runtime` 인터페이스를 중심에 두고 transport/adapters/store는 바깥쪽 구현으로 둔다. - 새 node 어댑터는 `runtime.Adapter`를 구현하고 `apps/node/internal/bootstrap/module.go`에서 registry에 등록한다. - 내부 실행 요청과 상태 저장에서는 `adapter`, `target`, `execution` 용어를 우선한다. `model`은 외부 API 호환이나 legacy placeholder일 때만 허용한다. -- Control Plane은 Node를 직접 연결/스케줄링하지 않고 Edge를 통해 시스템을 제어한다. Edge는 자신의 로컬 런타임 상태와 Node registry를 소유한다. +- Control Plane은 Node를 직접 연결/스케줄링하지 않고 Edge를 통해 시스템을 제어한다. Edge는 자신의 설정, 로컬 런타임 상태, Node registry의 원본을 소유한다. 여러 Control Plane이 있더라도 Edge는 실질 데이터 이전 없이 다른 Control Plane으로 연결 대상을 옮길 수 있어야 한다. - 사용자 실행, 로컬/dev 배포, field 테스트, 임시 Control Plane 대체 흐름은 사용법을 `scripts/dev/`, 보조 smoke script, 별도 dev deploy 바이너리, 모델용 skill로 흩뜨리지 않고 `iop-edge`와 `iop-node` command 표면에 모은다. helper script가 필요해도 공식 사용자 경로가 되면 안 된다. -- Control Plane이 없는 테스트/개발 배포 단계에서는 `edge.yaml`을 테스트용 Control Plane source of truth로 본다. Node별 id/alias/token/adapter/runtime 설정은 Edge config의 `nodes[]`에서 관리한다. +- Control Plane이 없는 테스트/개발 배포 단계에서는 `edge.yaml`을 테스트용 Edge-owned source of truth로 본다. Node별 id/alias/token/adapter/runtime 설정은 Edge config의 `nodes[]`에서 관리한다. - Node 사용자 UX는 bootstrap 명령 하나로 끝나야 한다. 사용자가 `node.yaml`을 만들거나 편집하거나 `iop-node serve --config ...`를 직접 실행하는 흐름을 기본 경로로 두지 않는다. bootstrap 내부에서 임시 상태나 설정 파일을 만들 수 있더라도 이는 구현 세부이며 사용자 가이드와 기본 운영 UX에 노출하지 않는다. - 바이너리 배포 UX는 repo checkout 위치에 묶이지 않아야 한다. `iop-edge`/`iop-node`는 아무 작업 디렉터리에서 실행 가능해야 하며, 로컬/dev bundle에서는 Edge 설정을 바이너리와 같은 디렉터리의 `edge.yaml` 같은 구조화된 config에 모으는 방향을 우선한다. Node 쪽은 별도 사용자 config 파일이 아니라 Edge가 제공하는 bootstrap으로 연결한다. - Edge-Node 내부 통신은 TCP 기반 protobuf 메시지 흐름을 우선한다. 브라우저/앱 표면이 필요한 경계는 proto-socket WebSocket/WSS를 사용할 수 있다. gRPC 도입, Edge-Node 기본 transport의 WebSocket 전환, actor/FSM/plugin framework 도입은 금지한다. diff --git a/agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md b/agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md index 4290371..509dac2 100644 --- a/agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md +++ b/agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md @@ -7,8 +7,8 @@ ## 목표 -여러 Edge group을 관찰하고 운영하는 fleet-level 기능을 구축한다. -Multi-edge scheduling과 fleet-wide state ownership은 Control Plane과 IOP native protocol에서 결정한다. +여러 Edge group을 연결하고 운영하는 fleet-level 기능을 구축한다. +Control Plane은 Edge를 제어하기 쉽게 연결하는 레이어이며, Edge의 설정과 실질 상태 원본은 Edge가 소유한다. ## 상태 @@ -16,31 +16,31 @@ Multi-edge scheduling과 fleet-wide state ownership은 Control Plane과 IOP nati ## 구현 잠금 -- 상태: 잠금 -- 결정 필요: 아래 체크리스트 - - [ ] Multi-Edge 1차 범위를 observe-only로 둘지, fleet-wide 명령까지 포함할지 결정한다. - - [ ] Control Plane과 Edge 사이의 상태 소유권과 aggregation 깊이를 결정한다. - - [ ] OTO/build-deploy domain agent 상태를 fleet 화면의 1차 범위에 포함할지 결정한다. +- 상태: 해제 +- 결정 필요: 없음 (아래 결정 기록) + - [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 등록/상태 표시 -- Edge별 runtime/automation 상태 집계 -- Edge 단위 실행 이력과 event aggregation +- 여러 Edge group 등록/연결/health 표시 +- Edge가 제공하는 runtime/automation capability와 운영 가능 상태 요약 +- Edge 단위 실행/명령 결과와 event relay - Edge 단위 작업 실행과 제어 -- OTO 같은 domain agent의 build/deploy 상태, artifact, capability 포함 -- fleet-wide 명령과 운영 리포트 후보 +- OTO 같은 domain agent의 build/deploy capability, ready/busy/error 상태, 명령 요청/진행/결과 요약 포함 +- fleet-wide 명령과 운영 리포트 ## 기능 ### Epic: [fleet-ops-boundary] Fleet Operations Boundary -- [ ] [native-fleet] Multi-edge 운영 명령과 이벤트 집계는 IOP native protocol을 기준으로 설계한다. +- [ ] [native-fleet] Multi-edge 운영 명령과 이벤트 relay는 IOP native protocol을 기준으로 설계한다. - [ ] [edge-status-view] Control Plane은 여러 Edge 상태를 구분해 조회하고 표시할 수 있다. 검증: 두 개 이상의 Edge 상태가 구분되는 조회/표시 경로를 확인한다. -- [ ] [history-agent-state] Edge별 실행 이력과 domain agent 상태가 운영 화면에서 구분된다. -- [ ] [openai-routing] OpenAI-compatible 표면은 특정 Edge/adapter로 라우팅되는 inference 호환 경로로 제한한다. -- [ ] [a2a-routing] A2A 표면은 특정 Edge/adapter로 위임되는 agent task 경로로 제한한다. -- [ ] [edge-ownership] Edge는 자신의 로컬 런타임 상태와 registry 소유권을 유지하고 fleet-wide 기능은 이를 침범하지 않는다. +- [ ] [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 경로로 제한한다. +- [ ] [edge-ownership] Edge는 설정, Node registry, 로컬 런타임 상태의 원본 소유권을 유지하고, Control Plane은 이동 가능한 제어 attachment로만 동작한다. ## 완료 리뷰 @@ -55,13 +55,19 @@ Multi-edge scheduling과 fleet-wide state ownership은 Control Plane과 IOP nati ## 범위 제외 - 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는 로컬 런타임 상태와 registry 소유권을 유지하고, Control Plane은 관찰/집계 계층으로 시작한다. +- 표준선(선택): Edge는 설정, 로컬 런타임 상태, Node registry의 원본 소유권을 유지하고, Control Plane은 연결/health 확인을 기반으로 fleet-wide 명령과 제어를 조율한다. Control Plane 교체나 이전은 Edge 실질 데이터 이전을 요구하지 않아야 한다. - 선행 작업: Control Plane과 Client, 정책/이력/감사 - 후속 작업: 없음 -- 확인 필요: observe-only 여부, fleet-wide 명령 범위, domain agent fleet 상태 포함 여부 +- 결정됨: 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` 통과. diff --git a/agent-task/m-multi-edge-operations/01_native_contract/CODE_REVIEW-cloud-G06.md b/agent-task/m-multi-edge-operations/01_native_contract/CODE_REVIEW-cloud-G06.md new file mode 100644 index 0000000..1bb69f7 --- /dev/null +++ b/agent-task/m-multi-edge-operations/01_native_contract/CODE_REVIEW-cloud-G06.md @@ -0,0 +1,39 @@ + +# Code Review - Native Fleet Contract + +## Review Scope + +- `proto/iop/control.proto` +- proto generated files +- `apps/control-plane/internal/wire/edge.go` +- `apps/edge/internal/controlplane/connector.go` +- ownership guard tests + +## Roadmap Targets + +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[native-fleet]` +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[edge-ownership]` + +## Reviewer Checklist + +- [ ] Control Plane이 Edge 설정, Node registry, runtime/automation state 원본을 소유하는 필드나 저장소가 생기지 않았다. +- [ ] OTO/build-deploy는 capability/status/command summary로만 표현된다. +- [ ] command 요청/응답/event relay 메시지가 request/result 추적에 충분하다. +- [ ] parser map이 양쪽에서 대칭적으로 갱신되었다. +- [ ] proto 생성물이 누락되지 않았다. +- [ ] 실패/unknown enum 처리 테스트가 있다. + +## Verification Result + +- [ ] `make proto` +- [ ] `make proto-dart` +- [ ] `go test ./apps/control-plane/internal/wire ./apps/edge/internal/controlplane` +- [ ] 필요한 경우 `cd apps/client && flutter test` + +## User Review + +검토 기본값: 이 리뷰는 사용자가 명시적으로 보류하지 않으면 구현자가 자체 검증 후 완료 처리한다. + +## Notes + +- 리뷰 중 발견한 계약 변경은 후속 plan의 구현 전제에 영향을 주므로 milestone 작업 맥락에 함께 반영한다. diff --git a/agent-task/m-multi-edge-operations/01_native_contract/PLAN-cloud-G06.md b/agent-task/m-multi-edge-operations/01_native_contract/PLAN-cloud-G06.md new file mode 100644 index 0000000..2ebb75c --- /dev/null +++ b/agent-task/m-multi-edge-operations/01_native_contract/PLAN-cloud-G06.md @@ -0,0 +1,99 @@ + +# Plan - Native Fleet Contract + +## 작업 지시 + +Multi-Edge 운영의 첫 구현 단위는 native wire 계약이다. Control Plane은 Edge의 실질 데이터 원본을 소유하지 않고, Edge가 제공하는 연결/health, capability/status, command 결과, event relay만 다루도록 proto와 wire parser 계약을 확장한다. + +## Roadmap Targets + +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[native-fleet]` +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[edge-ownership]` +- 완료 방식: 이 plan의 검증이 통과하면 위 target 중 "계약/소유권 가드" 범위의 완료 근거를 milestone에 추가한다. 전체 UI/API 완료는 후속 plan에서 닫는다. + +## 분석 결과 + +현재 native contract는 hello/status/node snapshot까지만 있다. + +```proto +// proto/iop/control.proto:67 +message EdgeStatusRequest { + string request_id = 1; +} + +// proto/iop/control.proto:85 +message EdgeStatusResponse { + string request_id = 1; + string edge_id = 2; + string status = 3; + repeated EdgeNodeSnapshot nodes = 4; +} +``` + +Control Plane parser도 현재 hello/status/node event만 받는다. + +```go +// apps/control-plane/internal/wire/edge.go:12 +func EdgeParserMap() iopwire.ParserMap { + return iopwire.ParserMap{ + iopcontrolv1.MessageType_MESSAGE_TYPE_EDGE_HELLO_REQUEST: func(payload []byte) (proto.Message, error) { +``` + +Edge connector 역시 status 요청만 처리하고, capability는 hello의 문자열 목록으로만 표현한다. + +```go +// apps/edge/internal/controlplane/connector.go:41 +type StatusProvider interface { + ListNodeSnapshots() []service.NodeSnapshot +} + +// apps/edge/internal/controlplane/connector.go:237 +func (c *Connector) sendHello(ctx context.Context, client iopwire.Client) error { +``` + +## 구현 체크리스트 + +1. `proto/iop/control.proto`에 fleet command/control과 domain capability/status summary 메시지를 추가한다. +2. 메시지는 Edge source-of-truth 철학을 드러내야 한다. Control Plane이 Edge 설정/Node registry/runtime state 원본을 저장하는 필드는 추가하지 않는다. +3. `EdgeStatusResponse`에 Edge가 제공하는 capability/status summary를 포함한다. +4. command 요청/응답/이벤트 relay 메시지를 추가하되, artifact/log/detail store 원본을 Control Plane으로 끌어오지 않는다. +5. `apps/control-plane/internal/wire/edge.go`와 `apps/edge/internal/controlplane/connector.go` parser map을 새 메시지에 맞춰 갱신한다. +6. proto 생성물을 갱신한다. Go/Dart 생성물이 있는 경우 기존 생성 방식만 사용한다. +7. 소유권 회귀 테스트를 추가한다. Control Plane contract에 Edge config 원본 저장/Node registry 원본 저장/agent lifecycle detail 원본 저장 필드가 생기면 실패해야 한다. + +## 세부 설계 + +### Fleet Command 계약 + +- `EdgeCommandRequest`: `request_id`, `command_id`, `target_selector`, `operation`, `parameters` +- `EdgeCommandResponse`: `request_id`, `command_id`, `edge_id`, `status`, `summary`, `error` +- `EdgeCommandEvent`: `command_id`, `edge_id`, `phase`, `summary`, `occurred_at` + +`parameters`는 command-specific 원본이 아니라 요청 payload이다. 저장 책임은 Control Plane이 아니라 요청 audit 범위로 제한한다. + +### Domain Agent Summary 계약 + +- `EdgeCapabilitySummary`: `kind`, `available`, `status`, `summary` +- `EdgeDomainAgentSummary`: `agent_kind`, `available`, `lifecycle_state`, `active_command_id`, `summary` + +OTO/build-deploy는 여기에서 `agent_kind`와 상태 요약으로만 드러난다. artifact, build logs, deploy history 원본은 Edge 또는 domain agent 쪽에 남긴다. + +### Ownership Guard + +테스트는 proto 텍스트 또는 descriptor를 읽어 다음 계열의 필드명이 Control Plane 소유 모델로 들어오지 않는지 확인한다. + +- `edge_config_source`, `node_registry_source`, `artifact_store`, `build_log_store` +- Control Plane registry struct가 Edge 설정 원본 map을 갖지 않는지 확인한다. + +## 검증 + +- `make proto` +- `make proto-dart` +- `go test ./apps/control-plane/internal/wire ./apps/edge/internal/controlplane` +- proto 생성물이 Dart client와 맞물리는 경우 `cd apps/client && flutter test` + +## 완료 조건 + +- 새 native 메시지가 Go/Dart 생성물과 parser map에 반영된다. +- Control Plane이 Edge 실질 데이터 원본을 소유하지 않는다는 가드 테스트가 있다. +- 후속 plan에서 Edge 구현과 Control Plane API가 참조할 수 있는 command/status/capability contract가 안정적으로 존재한다. diff --git a/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/CODE_REVIEW-cloud-G05.md b/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/CODE_REVIEW-cloud-G05.md new file mode 100644 index 0000000..01795e0 --- /dev/null +++ b/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/CODE_REVIEW-cloud-G05.md @@ -0,0 +1,30 @@ + +# 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 + +- [ ] `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 + +- [ ] `go test ./apps/edge/internal/service ./apps/edge/internal/controlplane` +- [ ] 필요한 경우 `go test ./apps/edge/...` + +## User Review + +검토 기본값: 이 리뷰는 사용자가 명시적으로 보류하지 않으면 구현자가 자체 검증 후 완료 처리한다. diff --git a/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/PLAN-cloud-G05.md b/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/PLAN-cloud-G05.md new file mode 100644 index 0000000..a25f3c4 --- /dev/null +++ b/agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/PLAN-cloud-G05.md @@ -0,0 +1,82 @@ + +# Plan - Edge Fleet Operations + +## 작업 지시 + +Edge에 native fleet command 처리, capability/status summary, command event relay를 구현한다. 이 plan은 `01_native_contract` 완료 뒤에만 실행한다. + +## 선행 의존성 + +- 필요: `agent-task/m-multi-edge-operations/01_native_contract/complete.log` +- 현재 상태: missing. 구현 시작 전 반드시 선행 plan 완료 로그를 확인한다. + +## 분석 결과 + +Edge connector는 Control Plane의 status request만 처리한다. + +```go +// apps/edge/internal/controlplane/connector.go:226 +func (c *Connector) handleStatusRequest(ctx context.Context, client iopwire.Client, envelope iopwire.Envelope) { +``` + +Edge service는 실행 요청과 취소 요청을 이미 Edge-local 책임으로 처리한다. + +```go +// apps/edge/internal/service/service.go:161 +func (s *Service) SubmitRun(ctx context.Context, req RunRequest) (*RunResult, error) { +``` + +Node snapshot에는 agent kind와 lifecycle state가 있으나 native status response로는 아직 나가지 않는다. + +```go +// apps/edge/internal/service/service.go:41 +type NodeSnapshot struct { + ID string + Alias string +``` + +## 구현 체크리스트 + +1. `StatusProvider`에 capability/status/domain agent summary를 제공하는 메서드를 추가한다. +2. `service.Service`가 NodeSnapshot 기반으로 OTO/build-deploy summary를 만들 수 있게 한다. +3. Edge connector가 새 `EdgeCommandRequest`를 받고 Edge-local service에 위임한다. +4. command result와 progress event를 native wire로 Control Plane에 relay한다. +5. command가 지원되지 않거나 busy/error 상태이면 Edge가 명확한 response를 반환한다. +6. Control Plane 연결 변경이 Edge-owned 설정/runtime state를 바꾸지 않는다는 테스트를 유지한다. + +## 세부 설계 + +### Capability Summary + +- 기존 `Service.Capabilities()`와 NodeSnapshot의 `AgentKind`, `LifecycleState`를 사용한다. +- `history-agent-state` 범위에 필요한 값은 summary로 제한한다. +- 상세 lifecycle history, build artifact, deploy logs는 전송하지 않는다. + +### Command Handling + +- connector에 command request handler를 추가한다. +- operation은 초기에 좁게 시작한다. + - `health.check` + - `agent.status` + - `agent.command` 또는 proto contract에서 확정된 이름 +- Edge가 처리하지 못하는 operation은 `unsupported` response로 끝낸다. +- command progress는 bounded event 형태로 relay한다. + +### Tests + +- command request를 받으면 service mock/provider가 호출된다. +- unsupported command는 실패 response를 전송한다. +- status response에 OTO/build-deploy summary가 들어간다. +- config secret은 status/capability summary에서 노출되지 않는다. +- Control Plane attach 정보 변경이 Edge source-of-truth 필드를 덮어쓰지 않는다. + +## 검증 + +- `go test ./apps/edge/internal/service ./apps/edge/internal/controlplane` +- 필요한 경우 `go test ./apps/edge/...` + +## 완료 조건 + +- Edge가 fleet command를 Edge-owned 처리로 받아 결과를 돌려준다. +- Edge status에 domain agent capability/status summary가 포함된다. +- command/event relay는 연결 Control Plane에 전달되지만 Edge 데이터 원본은 Edge에 남는다. diff --git a/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/CODE_REVIEW-cloud-G06.md b/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/CODE_REVIEW-cloud-G06.md new file mode 100644 index 0000000..7054d78 --- /dev/null +++ b/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/CODE_REVIEW-cloud-G06.md @@ -0,0 +1,33 @@ + +# Code Review - Control Plane Fleet API + +## Review Scope + +- `apps/control-plane/internal/wire/edge_server.go` +- `apps/control-plane/internal/wire/edge_registry.go` +- `apps/control-plane/cmd/control-plane/main.go` +- Control Plane API/wire tests + +## Dependency Check + +- [ ] `agent-task/m-multi-edge-operations/01_native_contract/complete.log` 확인 +- [ ] `agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/complete.log` 확인 + +## Reviewer Checklist + +- [ ] Control Plane 저장 모델이 connection/control/audit view에 머문다. +- [ ] Edge 설정/Node registry/runtime 원본을 복제하지 않는다. +- [ ] command routing이 edge별 active client로 정확히 분리된다. +- [ ] offline/reconnect/timeout 응답이 명확하다. +- [ ] bounded audit/event 저장 정책이 있다. +- [ ] 기존 Edge 목록/status/events API가 회귀하지 않았다. + +## Verification Result + +- [ ] `go test ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane` +- [ ] 필요한 경우 `go test ./apps/control-plane/...` +- [ ] 존재 시 `make test-control-plane-edge-wire` + +## User Review + +검토 기본값: 이 리뷰는 사용자가 명시적으로 보류하지 않으면 구현자가 자체 검증 후 완료 처리한다. diff --git a/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/PLAN-cloud-G06.md b/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/PLAN-cloud-G06.md new file mode 100644 index 0000000..93ad31a --- /dev/null +++ b/agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/PLAN-cloud-G06.md @@ -0,0 +1,87 @@ + +# Plan - Control Plane Fleet API + +## 작업 지시 + +Control Plane에 multi-edge command API, command result/event relay, fleet status summary API를 구현한다. Control Plane은 attachable control layer이므로 Edge 원본 데이터 저장소를 만들지 않는다. + +## 선행 의존성 + +- 필요: `agent-task/m-multi-edge-operations/01_native_contract/complete.log` +- 필요: `agent-task/m-multi-edge-operations/02+01_edge_fleet_ops/complete.log` +- 현재 상태: missing. 구현 시작 전 선행 plan 완료 로그를 확인한다. + +## 분석 결과 + +현재 HTTP API는 Edge 목록, 상세, 이벤트, live status 조회만 제공한다. + +```go +// apps/control-plane/cmd/control-plane/main.go:182 +registryMux.HandleFunc("/edges", app.handleEdges) +registryMux.HandleFunc("/edges/", app.handleEdgeDetail) +``` + +Edge server는 active client에 status request만 보낼 수 있다. + +```go +// apps/control-plane/internal/wire/edge_server.go:192 +func (s *EdgeServer) RequestStatus(ctx context.Context, edgeID string) (*iopcontrolv1.EdgeStatusResponse, error) { +``` + +Registry는 연결 상태와 최근 node event만 보관한다. + +```go +// apps/control-plane/internal/wire/edge_registry.go:12 +type EdgeRegistry struct { + mu sync.RWMutex + edges map[string]EdgeConnection + events map[string][]EdgeNodeEventRecord +``` + +## 구현 체크리스트 + +1. `EdgeServer`에 command request 전송과 response/event 수신 경로를 추가한다. +2. `EdgeRegistry`에는 connection view, command request/result, bounded event/audit만 저장한다. +3. HTTP API를 추가한다. + - `GET /edges/{id}/status` + - `GET /edges/{id}/operations` + - `POST /edges/{id}/commands` + - `GET /fleet/status` + - 필요한 경우 `POST /fleet/commands` +4. API 응답은 Edge-owned source summary만 포함하고 설정/registry/runtime 원본 복제를 하지 않는다. +5. 여러 Edge가 연결된 상황에서 command routing이 target Edge로만 가는지 테스트한다. +6. audit/event 저장은 bounded로 유지한다. + +## 세부 설계 + +### Command API + +- HTTP request는 native command request로 변환한다. +- `edge_id`, `command_id`, `operation`, `status`, `summary`, `created_at`, `updated_at` 중심으로 응답한다. +- command detail payload는 요청/결과 요약까지만 보관한다. + +### Fleet Status API + +- fleet 전체 목록은 연결/health와 Edge-provided capability summary를 합친 view이다. +- Edge 상태 조회 실패는 해당 Edge의 degraded/error view로 표현한다. +- Control Plane 단독 판단으로 agent lifecycle 원본 상태를 만들지 않는다. + +### Tests + +- 두 Edge 연결 후 각 Edge로 command가 분리 routing된다. +- offline Edge command는 적절한 error를 반환한다. +- command result/event가 bounded audit로 저장된다. +- API 응답에 Edge config secret과 runtime detail 원본이 포함되지 않는다. +- 기존 `/edges`, `/edges/{id}/status`, `/edges/{id}/events` 회귀 테스트가 통과한다. + +## 검증 + +- `go test ./apps/control-plane/internal/wire ./apps/control-plane/cmd/control-plane` +- 필요한 경우 `go test ./apps/control-plane/...` +- `make test-control-plane-edge-wire`가 존재하면 실행한다. + +## 완료 조건 + +- Control Plane이 여러 Edge에 command/control 요청을 보낼 수 있다. +- Edge status와 command result/event가 Control Plane API로 조회된다. +- 저장 모델은 connection/control/audit view로 제한된다. diff --git a/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/CODE_REVIEW-cloud-G05.md b/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/CODE_REVIEW-cloud-G05.md new file mode 100644 index 0000000..608e372 --- /dev/null +++ b/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/CODE_REVIEW-cloud-G05.md @@ -0,0 +1,37 @@ + +# Code Review - Client Fleet UI + +## Review Scope + +- `apps/client/lib/control_plane_status_client.dart` +- `apps/client/lib/control_plane_status_widgets.dart` +- `apps/client/lib/main.dart` +- `apps/client/test/widget_test.dart` + +## Roadmap Targets + +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[edge-status-view]` +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[history-agent-state]` + +## Dependency Check + +- [ ] `agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/complete.log` 확인 + +## Reviewer Checklist + +- [ ] Client 모델이 Control Plane view만 표현하고 Edge 원본 저장 모델을 암시하지 않는다. +- [ ] OTO/build-deploy 정보는 summary/status 수준으로 표시된다. +- [ ] multi-edge 상태와 command status가 사용자가 스캔하기 쉽게 표시된다. +- [ ] API failure/degraded/unknown state가 UI에서 명확하다. +- [ ] mobile/desktop에서 overflow와 overlap이 없다. +- [ ] 기존 Edges/Nodes/Execution Logs 회귀 테스트가 유지된다. + +## Verification Result + +- [ ] `cd apps/client && flutter test` +- [ ] `cd apps/client && flutter analyze --no-fatal-infos` +- [ ] 원격 runner 사용 시 동기화/실행 로그 첨부 + +## User Review + +검토 기본값: 이 리뷰는 사용자가 명시적으로 보류하지 않으면 구현자가 자체 검증 후 완료 처리한다. diff --git a/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/PLAN-cloud-G05.md b/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/PLAN-cloud-G05.md new file mode 100644 index 0000000..89e0f9c --- /dev/null +++ b/agent-task/m-multi-edge-operations/04+03_client_fleet_ui/PLAN-cloud-G05.md @@ -0,0 +1,89 @@ + +# Plan - Client Fleet UI + +## 작업 지시 + +Client portal에 multi-edge fleet status, Edge별 command 상태, OTO/build-deploy domain agent summary를 표시한다. 이 plan은 Control Plane fleet API 완료 뒤에 실행한다. + +## Roadmap Targets + +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[edge-status-view]` +- `agent-roadmap/phase/control-plane-portal-ops/milestones/multi-edge-operations.md` `[history-agent-state]` +- 완료 방식: 선행 plan 검증과 이 UI 검증이 모두 통과하면 두 target을 완료 처리한다. + +## 선행 의존성 + +- 필요: `agent-task/m-multi-edge-operations/03+01,02_control_plane_fleet_api/complete.log` +- 현재 상태: missing. 구현 시작 전 선행 plan 완료 로그를 확인한다. + +## 분석 결과 + +Client repository는 `/edges`, `/edges/{id}/status`, `/edges/{id}/events`만 읽는다. + +```dart +// apps/client/lib/control_plane_status_client.dart:175 +class ControlPlaneStatusRepository { + ControlPlaneStatusRepository({ +``` + +현재 UI는 Edges, Nodes, Execution Logs 패널로 구성되어 있다. + +```dart +// apps/client/lib/control_plane_status_widgets.dart:4 +class EdgesPanel extends StatelessWidget { +``` + +Widget test는 두 Edge와 node/event 표시 회귀를 검증한다. + +```dart +// apps/client/test/widget_test.dart:1 +import 'dart:async'; +``` + +## 구현 체크리스트 + +1. Control Plane fleet API 응답 모델을 Dart client에 추가한다. +2. Edge별 capability/status/domain agent summary 모델을 추가한다. +3. UI에 fleet health와 Edge별 command 상태를 표시한다. +4. OTO/build-deploy domain agent summary를 별도 패널 또는 Nodes 패널의 안정적인 섹션으로 표시한다. +5. command 실행 버튼은 검증된 API 범위가 있을 때만 추가한다. API가 summary-only이면 실행 버튼 없이 상태/결과 표시만 구현한다. +6. mobile/desktop에서 텍스트 overflow와 panel overlap을 확인한다. +7. existing widget tests를 확장해 두 Edge, domain agent summary, command 상태를 검증한다. + +## 세부 설계 + +### Data Model + +- `EdgeCapabilityStatus` +- `EdgeDomainAgentStatus` +- `EdgeOperationStatus` +- `FleetStatus` + +모델은 Control Plane API view에 맞추되, Edge config/runtime original detail을 표현하는 필드는 추가하지 않는다. + +### UI + +- Edges panel은 연결/health와 capability summary를 함께 보여준다. +- Nodes panel은 Edge-owned node summary만 보여준다. +- 새 Operation/Agent panel은 `ready`, `busy`, `error`, `unknown` 같은 짧은 상태 중심으로 구성한다. +- 실행 로그 패널은 command event relay를 보여주되 artifact/log 원본 뷰어로 확장하지 않는다. + +### Tests + +- fake repository에 fleet status와 domain agent summary fixture를 추가한다. +- UI가 두 Edge의 capability/status를 표시하는지 검증한다. +- OTO/build-deploy summary가 표시되는지 검증한다. +- API failure는 degraded/unknown state로 표시된다. +- 버튼/라벨 텍스트가 작은 화면에서 overflow하지 않도록 golden 또는 widget-level layout 검증을 추가한다. + +## 검증 + +- `cd apps/client && flutter test` +- `cd apps/client && flutter analyze --no-fatal-infos` +- 원격 Flutter runner가 필요한 환경이면 runner 동기화 후 같은 명령을 실행한다. + +## 완료 조건 + +- Client에서 multi-edge connection/health, command status, OTO/build-deploy summary가 확인된다. +- UI는 Control Plane을 Edge data owner로 보이게 만들지 않는다. +- `[edge-status-view]`, `[history-agent-state]` 완료 근거를 milestone에 남길 수 있다. diff --git a/apps/control-plane/README.md b/apps/control-plane/README.md index 2068edc..abbf4b9 100644 --- a/apps/control-plane/README.md +++ b/apps/control-plane/README.md @@ -1,18 +1,18 @@ # control-plane — Control Plane -여러 Edge를 연결하고 관찰하며, Edge 설정 변경과 명령 전달을 담당할 Go 기반 중앙 관리 서버다. +여러 Edge를 연결하고 제어하며, Edge 설정 변경 요청과 명령 전달을 담당할 Go 기반 운영 제어 서버다. Control Plane은 Edge 데이터의 원본 저장소가 아니라 연결된 Edge를 제어하기 쉽게 만드는 레이어다. **현재 상태: Scaffold** -현재 Control Plane은 실행 가능한 최소 서버 스캐폴드 단계다. Node를 직접 등록하거나 직접 스케줄링하는 계층으로 확정하지 않는다. Control Plane은 Edge를 통해 시스템을 제어하고, Edge가 자신의 로컬 런타임 상태와 Node registry를 운영하는 방향을 따른다. +현재 Control Plane은 실행 가능한 최소 서버 스캐폴드 단계다. Node를 직접 등록하거나 직접 스케줄링하는 계층으로 확정하지 않는다. Control Plane은 Edge를 통해 시스템을 제어하고, Edge가 자신의 설정, 로컬 런타임 상태와 Node registry를 운영하는 방향을 따른다. Edge는 다른 Control Plane으로 연결 대상을 옮겨도 실질 데이터 migration을 요구하지 않아야 한다. IOP의 프론트엔드는 Control Plane 내부 UI가 아니라 Flutter-first Client로 둔다. Client의 기준 구현은 `apps/client`의 Flutter 앱이고, web 배포는 `apps/client/Dockerfile`이 빌드한 Flutter Web 산출물을 compose `web` 서비스에서 nginx로 정적 서빙한다. Client-Control Plane 통신은 proto-socket WebSocket/WSS를 우선하고, Control Plane-Edge 통신은 edge-node에서 사용 중인 proto-socket 흐름을 IOP Wire Protocol 기준으로 확장한다. `net/http`는 health/readiness/bootstrap 같은 보조 endpoint 용도로만 둔다. ## 운영 경계 -Control Plane은 상시 운영, multi-edge 관찰/명령, 정책/감사 UX의 계획된 기본 운영면이다. Edge-local bootstrap, bundle-local config, env/config 진단, node 등록 command 발급, smoke, 단일 Edge 유지보수 fallback은 `iop-edge` CLI에 남긴다. +Control Plane은 상시 운영, multi-edge 연결/health 확인, fleet-wide 명령, 정책/감사 UX의 계획된 기본 운영면이다. Edge-local bootstrap, bundle-local config, env/config 진단, node 등록 command 발급, smoke, 단일 Edge 유지보수 fallback은 `iop-edge` CLI에 남긴다. -Control Plane-Edge wire protocol은 Edge가 소유한 operation을 원격 운영면으로 소비한다. Edge 상태 조회, node 및 후속 agent 등록 상태 조회, command 전달, event 수신, run/cancel/status, bootstrap 발급 상태처럼 CLI와 Control Plane에 모두 필요한 작업은 Edge 내부의 표면 중립 service/operation boundary로 수렴시키고, Control Plane에서 Edge-local registry, run dispatch, stream relay 구현을 복제하지 않는다. +Control Plane-Edge wire protocol은 Edge가 소유한 operation을 원격 운영면으로 소비한다. Edge 상태 조회, node 및 후속 agent 등록 상태 조회, command 전달, event 수신, run/cancel/status, bootstrap 발급 상태처럼 CLI와 Control Plane에 모두 필요한 작업은 Edge 내부의 표면 중립 service/operation boundary로 수렴시키고, Control Plane에서 Edge-local registry, run dispatch, stream relay 구현을 복제하지 않는다. Control Plane이 보관할 수 있는 정보는 연결 view, 제어 요청/결과, audit에 필요한 최소 운영 기록으로 제한한다. ## 현재 실행 표면 @@ -32,7 +32,7 @@ Control Plane-Edge wire protocol은 Edge가 소유한 operation을 원격 운영 - Go 단일 바이너리 운영 제어 서버 - 여러 Edge 연결 관리 - Edge 상태 조회 -- Edge 설정 변경 +- Edge 설정 변경 요청 - Edge 명령 전달 - Edge 이벤트 수신 - Policy/Config, Job/Worker, Audit, Metrics/Event API 제공 diff --git a/apps/edge/README.md b/apps/edge/README.md index 87ce865..9fecdbc 100644 --- a/apps/edge/README.md +++ b/apps/edge/README.md @@ -116,7 +116,7 @@ Node host는 `/bootstrap/node.sh` 하나를 실행하고, boo `iop-edge` CLI는 Control Plane이 없거나 아직 연결되지 않은 host에서도 Edge를 설치, 진단, 복구할 수 있게 하는 local/field/fallback interface다. 상시 multi-edge 운영 UI/API는 Control Plane으로 확장하고, CLI를 fleet 운영 화면으로 키우지 않는다. - **Edge-local 필수**: `config init/check/print`, `env`, `setup`, `bootstrap pack`, `node register`, `nodes list`, `smoke`, 단일 Edge `serve`/`console` -- **Control Plane 기본**: 여러 Edge 상태 조회, 팀 운영 UI, 정책/권한/audit, 반복 운영/리포트, fleet-wide command +- **Control Plane 기본**: 여러 Edge 연결/health 확인, 팀 운영 UI, 정책/권한/audit, 반복 운영/리포트, fleet-wide command - **Shared operation**: Edge 상태 조회, node 및 후속 agent 등록 상태 조회, command 전달, event 수신, run/cancel/status, bootstrap 발급 상태 새 command나 운영 기능은 먼저 위 category 중 하나로 분류한다. CLI와 Control Plane에 모두 필요한 작업은 표면별로 registry 변경, run dispatch, command request 로직을 복제하지 않고 `apps/edge/internal/service` 같은 표면 중립 Edge operation boundary로 수렴시킨다. 후속 specialized agent enrollment, remote terminal bridge, Cline 확장도 새 command가 필요하면 이 분류를 먼저 따른다.