<!-- task=m-oto-specific-iop-removal/02+01_runtime_fixture_cleanup plan=0 tag=REFACTOR -->

# Plan - REFACTOR Runtime And Fixture OTO Cleanup

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

이 subtask는 `01_config_cli_cleanup` 완료 후 실행한다. 구현 완료 전 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 직접 사용자 질문, `USER_REVIEW.md` 작성, `complete.log` 작성, archive 이동은 금지다.

## 배경

config/CLI에서 OTO 전용 kind가 사라지면 Edge transport/service와 운영 fixture에서도 OTO 전용 lifecycle, capability, domain-agent 예시를 제거해야 한다. Control Plane과 Client fixture는 generic domain-agent 예시를 유지할 수 있지만 `oto`/`oto-agent` 이름은 제거해야 한다.

## 사용자 리뷰 요청 흐름

구현 중 사용자 결정이 필요하면 active review stub의 `사용자 리뷰 요청`에 근거와 재개 조건을 기록하고 멈춘다. 자동 후속으로 검증 재실행이 가능한 증거 공백은 사용자 리뷰 요청이 아니다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-specific-iop-removal.md`
- Task ids:
  - `runtime-cleanup`: Edge registry, transport, service snapshot, Control Plane/Client fixture에서 OTO 전용 조건 분기와 표시 문구를 제거하거나 generic 표현으로 바꾼다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-specific-iop-removal.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-test/local/control-plane-smoke.md`
- `agent-test/local/client-smoke.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/control-plane/rules.md`
- `agent-ops/rules/project/domain/client/rules.md`
- `apps/edge/internal/node/mapper.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/node/registry.go`
- `apps/edge/internal/node/mapper_test.go`
- `apps/edge/internal/node/registry_test.go`
- `apps/edge/internal/node/store_test.go`
- `apps/edge/internal/service/service.go`
- `apps/edge/internal/service/service_test.go`
- `apps/edge/internal/transport/server.go`
- `apps/edge/internal/transport/integration_test.go`
- `apps/control-plane/cmd/control-plane/main_test.go`
- `apps/client/test/widget_test.dart`

### 테스트 환경 규칙

`test_env=local`이다. Matching profiles는 edge, control-plane, client smoke다. 적용 명령은 `go test ./apps/edge/...`, `go test ./apps/control-plane/...`, `cd apps/client && flutter test`다. client profile은 Flutter 검증이 원격 runner 기준임을 명시한다. 현재 checkout 변경이 원격에 동기화되지 않으면 remote 실행 결과를 완료 증거로 보지 않는다.

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

- Transport duplicate registration/lifecycle: `apps/edge/internal/transport/integration_test.go`가 직접 커버한다.
- Service capability/domain-agent synthesis: `apps/edge/internal/service/service_test.go`가 직접 커버한다.
- Control Plane fleet status fixture: `apps/control-plane/cmd/control-plane/main_test.go`가 직접 커버한다.
- Client domain-agent fixture/rendering: `apps/client/test/widget_test.dart`가 직접 커버한다.
- 실제 edge-node full-cycle은 이 subtask 단독 completion 기준이 아니다. 03 plan의 최종 검증에서 전체 검색과 통합 검증 여부를 기록한다.

### 심볼 참조

- `config.AgentKindOTOAgent`: `apps/edge/internal/node/*_test.go`, `apps/edge/internal/service/service.go`, `apps/edge/internal/service/service_test.go`, `apps/edge/internal/transport/server.go`, `apps/edge/internal/transport/integration_test.go`에 남아 있다.
- `oto`, `oto-agent`, `OTO`: Control Plane test fixture와 Client widget fixture/expectations에 남아 있다.

### 분할 판단

Shared task group은 `m-oto-specific-iop-removal`이다. 이 subtask는 `02+01_runtime_fixture_cleanup`이므로 predecessor index `01`이 필요하다. 현재 active `agent-task/m-oto-specific-iop-removal/01_*/complete.log`와 archive candidate complete.log는 없다. 구현 시작 전 runtime은 `01_config_cli_cleanup` PASS 완료를 확인해야 한다.

### 범위 결정 근거

이 plan은 Edge runtime/test fixture와 Control Plane/Client fixture만 다룬다. Config/CLI source 제거는 01 plan, docs/final search는 03 plan이다. Proto field 자체(`DomainAgents`)는 제거하지 않는다. Generic external/domain agent 계약 신규 설계는 Milestone 범위 제외다.

### 빌드 등급

`cloud-G06`: protocol lifecycle, service summary, Flutter fixture가 교차하며 검증이 여러 runner에 걸친다.

## 구현 체크리스트

- [ ] `apps/edge/internal/transport`에서 OTO 전용 duplicate reason, accepted/online heartbeat lifecycle 분기를 제거하고 tests를 generic node lifecycle 기준으로 갱신한다.
- [ ] `apps/edge/internal/service`에서 OTO 전용 build-deploy capability/domain-agent synthesis와 표시 문구를 제거하고 tests를 generic run capability 기준으로 갱신한다.
- [ ] `apps/edge/internal/node` tests에서 OTO 전용 record/agent kind fixture를 generic node fixture로 바꾼다.
- [ ] Control Plane/Client fixture에서 `oto`/`oto-agent`/`oto-agent.sync`를 generic domain-agent 예시로 바꾸고 관련 expectations를 갱신한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REFACTOR-1] Edge Transport And Node Runtime Cleanup

#### 문제

`apps/edge/internal/transport/server.go:164`-`184`가 OTO duplicate reason을 분기하고, `server.go:196`-`237`이 OTO만 `accepted` 후 heartbeat에서 `online`으로 바꾸는 lifecycle을 갖는다. `apps/edge/internal/transport/integration_test.go:68`-`130`, `integration_test.go:336`-`425`, `integration_test.go:544`-`557`이 이 전용 흐름을 보증한다.

#### 해결 방법

Before:

```go
reason := "node already connected"
if rec.AgentKind == config.AgentKindOTOAgent {
	reason = "oto agent already connected"
}
...
lifecycle := edgenode.LifecycleConnected
if rec.AgentKind == config.AgentKindOTOAgent {
	lifecycle = edgenode.LifecycleAccepted
}
```

After:

```go
reason := "node already connected"
lifecycle := edgenode.LifecycleConnected
```

Heartbeat listener special-case를 삭제한다. Tests는 generic node registration, duplicate rejection, heartbeat timeout만 유지한다.

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

- [ ] `apps/edge/internal/transport/server.go`: OTO-specific import/branches 제거.
- [ ] `apps/edge/internal/transport/integration_test.go`: OTO registration/first heartbeat tests 삭제 또는 generic lifecycle assertions로 전환.
- [ ] `apps/edge/internal/node/mapper_test.go`, `registry_test.go`, `store_test.go`: OTO-specific fixture names/kinds 제거.

#### 테스트 작성

기존 transport/node tests를 갱신한다. 별도 신규 test보다 `TestEdgeServerDuplicateRegistrationReason`, `TestEdgeServerIntegration`, `TestRegistryRegisterDefaultsKindAndLifecycle` 유지가 적합하다.

#### 중간 검증

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

### [REFACTOR-2] Service And UI Fixture Cleanup

#### 문제

`apps/edge/internal/service/service.go:551`-`624`가 OTO agent를 `build-deploy` capability와 domain-agent summary로 합성한다. `apps/control-plane/cmd/control-plane/main_test.go:723`-`725`와 `main_test.go:770`은 `oto` fixture를 사용한다. `apps/client/test/widget_test.dart:149`-`181`, `widget_test.dart:242`-`274`, `widget_test.dart:283`-`317`, `widget_test.dart:632`-`720`은 `oto-agent` UI fixture/expectations를 사용한다.

#### 해결 방법

Before:

```go
if snap.AgentKind == config.AgentKindOTOAgent {
	out = append(out, &iop.EdgeDomainAgentSummary{
		AgentKind: snap.AgentKind,
		Summary: fmt.Sprintf("OTO agent alias=%s state=%s", snap.Alias, snap.LifecycleState),
	})
}
```

After:

```go
return nil
```

`GetCapabilities`는 generic nodes가 있으면 `run` capability만 반환한다. Control Plane/Client tests는 `oto`/`oto-agent`를 `deployer` 또는 `build-deploy` 같은 generic fixture로 바꾸고, operations는 `deploy.sync` 같은 neutral operation으로 바꾼다.

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

- [ ] `apps/edge/internal/service/service.go`: OTO branch, build-deploy synthesis, OTO summary string 제거.
- [ ] `apps/edge/internal/service/service_test.go`: OTO cases를 generic node/domain-agent absence 또는 neutral fixture로 갱신.
- [ ] `apps/control-plane/cmd/control-plane/main_test.go`: `oto` domain-agent fixture를 neutral fixture로 변경.
- [ ] `apps/client/test/widget_test.dart`: `oto-agent` domain-agent/operation text를 neutral fixture로 변경.

#### 테스트 작성

기존 tests를 갱신한다. Client test는 UI가 neutral domain-agent label과 operations history를 계속 표시하는지 assertion을 유지한다.

#### 중간 검증

```bash
go test -count=1 ./apps/edge/internal/service ./apps/control-plane/cmd/control-plane
cd apps/client && flutter test
```

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `apps/edge/internal/transport/server.go` | REFACTOR-1 |
| `apps/edge/internal/transport/integration_test.go` | REFACTOR-1 |
| `apps/edge/internal/node/mapper_test.go` | REFACTOR-1 |
| `apps/edge/internal/node/registry_test.go` | REFACTOR-1 |
| `apps/edge/internal/node/store_test.go` | REFACTOR-1 |
| `apps/edge/internal/service/service.go` | REFACTOR-2 |
| `apps/edge/internal/service/service_test.go` | REFACTOR-2 |
| `apps/control-plane/cmd/control-plane/main_test.go` | REFACTOR-2 |
| `apps/client/test/widget_test.dart` | REFACTOR-2 |

## 의존 관계 및 구현 순서

이 subtask directory name은 `02+01_runtime_fixture_cleanup`이므로 `01_config_cli_cleanup`의 `complete.log`가 필요하다. 구현 시작 전에 active/archive predecessor completion을 확인하고, 없으면 구현하지 말고 review stub에 blocker가 아니라 dependency missing으로 기록한다.

## 최종 검증

```bash
go test -count=1 ./apps/edge/internal/node ./apps/edge/internal/service ./apps/edge/internal/transport ./apps/control-plane/cmd/control-plane
cd apps/client && flutter test
rg --sort path -n "AgentKindOTOAgent|\\bOTO\\b|\\boto\\b|oto-agent|OTOAgent" apps/edge/internal apps/control-plane/cmd/control-plane apps/client/test
```

기대 결과: Go tests 통과, Flutter test 통과 또는 runner 차단 근거 기록, `rg`는 제거 대상 없음. 모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
