<!-- task=01_edge_runtime_common plan=0 tag=ERC -->

# 01 Edge Runtime Common Plan - ERC

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

**필수: 구현 마지막에는 반드시 `CODE_REVIEW-*-G??.md`의 모든 섹션을 실제 구현 내용과 명령 출력으로 채운다.**
중간/최종 검증을 실행하고 `CODE_REVIEW-cloud-G07.md`를 채운다. 구현 에이전트는 review 파일의 아카이브 지시를 실행하지 않는다.

## 배경

Edge console을 ops/debug 표면으로 유지하려면 `serve`와 `console`이 같은 runtime 조립 경로를 써야 한다. 지금은 console이 logger, registry, node store, transport server, event bus, metrics를 직접 조립하고, serve는 fx module에서 별도 조립한다.

## 분석 결과

### 읽은 파일

- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `apps/edge/cmd/edge/main.go`
- `apps/edge/cmd/edge/console.go`
- `apps/edge/cmd/edge/console_test.go`
- `apps/edge/internal/bootstrap/module.go`
- `apps/edge/internal/transport/server.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/service/service.go`
- `apps/edge/internal/events/bus.go`
- `packages/config/config.go`

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

- 공통 runtime 생성/seed/handler wiring을 검증하는 테스트가 없다.
- console tests는 출력 helper 중심이라 runtime 중복 제거를 보장하지 않는다.

### 심볼 참조

- `runConsole`: `apps/edge/cmd/edge/console.go:23`, 호출 `apps/edge/cmd/edge/main.go:58`.
- `bootstrap.Module`: `apps/edge/internal/bootstrap/module.go:18`, 호출 `apps/edge/cmd/edge/main.go:43`.

### 범위 결정 근거

- Control Plane API 구현은 제외한다.
- transport 프로토콜 변경은 제외한다.
- Node adapter 실행 로직은 제외한다.

### 빌드 등급

- Build `cloud-G07`: edge bootstrap/cmd 경계와 bin-level smoke 영향이 있다.
- Review `cloud-G07`: runtime wiring과 실제 entrypoint 검증 증거가 필요하다.

### [ERC-1] 공통 runtime builder 추가

#### 문제

`console.go:23-63`과 `module.go:18-75`가 edge runtime 조립을 나눠 가진다.

#### 해결 방법

- `apps/edge/internal/bootstrap/runtime.go`에 `Runtime` 구조체와 `NewRuntime(cfg)`를 추가한다.
- `Runtime`은 `Logger`, `Registry`, `NodeStore`, `EventBus`, `Service`, `Server`를 보유한다.
- `Start(ctx)`에서 node store seed, event handler wiring, server start, metrics start를 처리한다.
- `Stop()`에서 server stop과 logger sync를 처리한다.

#### 수정 파일 및 체크리스트

- [ ] `apps/edge/internal/bootstrap/runtime.go`
- [ ] `apps/edge/internal/bootstrap/runtime_test.go`
- [ ] `apps/edge/internal/bootstrap/module.go`

#### 테스트 작성

- `TestNewRuntimeSeedsNodeStore`
- `TestRuntimeWiresTransportHandlers`

#### 중간 검증

```bash
go test -count=1 ./apps/edge/internal/bootstrap
```

### [ERC-2] serve/console이 공통 runtime 사용

#### 문제

`runConsole`이 직접 조립해서 serve와 lifecycle 차이가 생긴다.

#### 해결 방법

- `serve` path는 `bootstrap.Module` 내부에서 `Runtime`을 사용한다.
- `console` path는 `bootstrap.NewRuntime(cfg)` 후 `Start/Stop`을 호출한다.
- console loop는 runtime의 `Service`, `Registry`, `EventBus`만 참조한다.

#### 수정 파일 및 체크리스트

- [ ] `apps/edge/cmd/edge/console.go`
- [ ] `apps/edge/cmd/edge/main.go`
- [ ] `apps/edge/cmd/edge/console_test.go`

#### 테스트 작성

- 기존 console tests 유지.
- 필요 시 fake runtime을 주입할 수 있게 console loop를 분리한다.

#### 중간 검증

```bash
go test -count=1 ./apps/edge/cmd/edge ./apps/edge/internal/bootstrap
```

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `apps/edge/internal/bootstrap/runtime.go` | ERC-1 |
| `apps/edge/internal/bootstrap/runtime_test.go` | ERC-1 |
| `apps/edge/internal/bootstrap/module.go` | ERC-1, ERC-2 |
| `apps/edge/cmd/edge/console.go` | ERC-2 |
| `apps/edge/cmd/edge/main.go` | ERC-2 |
| `apps/edge/cmd/edge/console_test.go` | ERC-2 |

## 최종 검증

```bash
go test -count=1 ./apps/edge/internal/bootstrap ./apps/edge/cmd/edge
go test -count=1 ./...
```

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