<!-- task=m-multi-edge-operations/02+01_edge_fleet_ops plan=0 tag=API -->
# 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에 남는다.
