<!-- task=m-oto-agent-registry-implementation/03+01,02_service_snapshots plan=0 tag=OAR03 -->

# OTO Agent Registry - Service Snapshots

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

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증을 실행하고 실제 변경 내용과 stdout/stderr를 채운 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, 또는 범위 충돌 없이는 진행할 수 없을 때만 review stub의 `사용자 리뷰 요청` 섹션에 근거를 적고 중단한다. 재실행으로 해소 가능한 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

registry와 transport가 OTO kind를 보존해도 service layer snapshot에서 빠지면 운영 상태 확인과 후속 Control Plane 노출을 만들 수 없다. 이 계획은 Edge service 내부의 `NodeSnapshot`/`NodeEntrySnapshot`에 kind와 lifecycle을 추가해 OTO agent 상태 기반을 만든다. 기존 node 호환성을 확인하는 마지막 하위 작업이다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active `CODE_REVIEW-*-G??.md`의 `사용자 리뷰 요청` 섹션에 기록한다. `USER_REVIEW.md` 작성과 검증은 code-review가 담당한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
- Task ids:
  - `compat-node`: 기존 node 등록과 registry 동작이 회귀하지 않는다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-test/local/testing-smoke.md`
- `apps/edge/internal/service/service.go`
- `apps/edge/internal/service/service_test.go`
- `apps/edge/internal/bootstrap/runtime.go`
- `apps/edge/internal/bootstrap/runtime_test.go`
- `apps/edge/internal/node/registry.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/transport/server.go`

### 테스트 환경 규칙

`test_env=local`이다. 적용 프로필은 `edge-smoke`, `platform-common-smoke`, `testing-smoke`다. 계약 명령은 `go test -count=1 ./apps/edge/internal/service ./apps/edge/internal/bootstrap`와 최종 `go test -count=1 ./apps/edge/... ./packages/go/config`다.

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

- `ListNodeSnapshots`가 kind/lifecycle을 전달하는지: 신규 service test 필요.
- `NodeEntrySnapshot`가 connected OTO entry를 표현하는지: 신규 service test 필요.
- 기존 generic node snapshot 기본값 회귀: 기존 service/bootstrap tests 보강 필요.
- Control Plane wire에는 아직 필드가 없어 외부 노출 테스트는 이번 범위에서 제외한다.

### 심볼 참조

rename/remove 없음. 관련 call site는 `edgeservice.Service.ListNodeSnapshots`, `NodeSnapshot`, `NodeEntrySnapshot`, `controlplane.Connector`의 read-only 사용, opsconsole status/events/console의 read-only 사용이다. 새 필드 추가는 기존 composite literal 컴파일 영향 여부를 확인해야 한다.

### 분할 판단

공유 task group은 `m-oto-agent-registry-implementation`이다. 이 작업은 `03+01,02_service_snapshots`이며 predecessor `01_config_store`와 `02+01_registry_transport`의 `complete.log`가 필요하다. 현재 작성 시점에는 둘 다 아직 완료되지 않았으므로 구현 전 active 또는 archive matching `complete.log`를 확인한다.

### 범위 결정 근거

이 단계는 Edge service 내부 snapshot과 테스트만 수정한다. Control Plane proto, Client UI, opsconsole 표시문구 개선, CLI bootstrap command, DB persistence, OTO message routing은 제외한다. 새 필드는 기존 consumers가 무시할 수 있는 additive struct field로 유지한다.

### 빌드 등급

`local-G06`: service DTO additive change이며 기존 tests와 focused package tests로 회귀를 확인할 수 있다.

## 구현 체크리스트

- [ ] 시작 전 `01_config_store`와 `02+01_registry_transport`의 `complete.log`로 predecessor 완료를 확인한다.
- [ ] `apps/edge/internal/service/service.go`의 snapshot structs와 snapshot 생성 경로에 `AgentKind`, `LifecycleState`를 추가한다.
- [ ] service/bootstrap 테스트에서 OTO entry snapshot과 generic node 호환성을 검증한다.
- [ ] 전체 Edge/package 회귀 검증을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [OAR03-1] Service snapshot kind fields

#### 문제

`apps/edge/internal/service/service.go:37`의 snapshot DTO는 connected entry의 kind와 lifecycle을 전달하지 않는다. `ListNodeSnapshots` consumer는 OTO 상태를 구분할 수 없다.

#### 해결 방법

`NodeSnapshot`과 `NodeEntrySnapshot`에 `AgentKind`, `LifecycleState`를 추가하고 registry entry에서 복사한다. 비연결 configured node는 `generic-node`와 empty/known lifecycle을 명시적으로 유지한다.

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

- [ ] `apps/edge/internal/service/service.go`: snapshot structs와 list/snapshot 생성 경로 수정.
- [ ] `apps/edge/internal/service/service_test.go`: OTO entry snapshot, generic node compatibility 테스트 추가.
- [ ] `apps/edge/internal/bootstrap/runtime_test.go`: runtime 구성 후 기존 node snapshot 회귀가 있으면 assertion 보강.

#### 테스트 작성

작성한다. `TestListNodeSnapshotsIncludesAgentKind`와 OTO entry lifecycle assertion을 추가한다.

#### 중간 검증

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

예상 결과: service/bootstrap package 테스트 PASS.

### [OAR03-2] Whole edge compatibility

#### 문제

새 필드는 service DTO와 registry/store를 가로지르므로 기존 generic node 등록 및 runtime bootstrap이 깨지지 않는지 package 단위로 확인해야 한다.

#### 해결 방법

기존 tests를 유지하면서 새 field 기본값이 기존 node 흐름에서 안정적으로 채워지는지 확인한다. Control Plane wire mapping은 필드 미노출 상태로 둔다.

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

- [ ] `apps/edge/internal/service/service_test.go`: generic node snapshot 기본값 확인.
- [ ] 필요하면 compile failure가 난 consumer test만 최소 수정한다.

#### 테스트 작성

작성한다. 신규 필드의 기존 node compatibility assertion을 추가한다.

#### 중간 검증

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

예상 결과: Edge 전체 테스트 PASS.

## 의존 관계 및 구현 순서

이 task directory의 `+01,02`는 `01_config_store`와 `02+01_registry_transport` 완료 의존성을 뜻한다. 구현 전 두 predecessor의 `complete.log`를 확인한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/edge/internal/service/service.go` | OAR03-1 |
| `apps/edge/internal/service/service_test.go` | OAR03-1, OAR03-2 |
| `apps/edge/internal/bootstrap/runtime_test.go` | OAR03-1, OAR03-2 |

## 최종 검증

```bash
go test -count=1 ./apps/edge/... ./packages/go/config
```

예상 결과: Edge 전체와 config package 테스트 PASS. Go test cache output은 허용하지 않는다.

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