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

# Plan - REFACTOR Config/CLI OTO Cleanup

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

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채우는 것이 필수다. 구현 후 검증을 실행하고 실제 변경 내용과 출력, 계획 대비 변경 사항을 review stub에 기록한 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌 없이는 사용자에게 직접 묻지 말고, 막히면 review stub의 `사용자 리뷰 요청` 섹션에 근거를 남긴다. `USER_REVIEW.md`, `complete.log`, archive 이동은 code-review 전용이다.

## 배경

현재 Milestone은 IOP에서 OTO 전용 registration/config/bootstrap 경로를 제거하는 작업이다. 가장 먼저 공통 config 계약과 `iop-edge` CLI 표면에서 `oto-agent`, `AgentKindOTOAgent`, OTO bootstrap/release config를 제거해야 뒤의 runtime cleanup이 안정적으로 진행된다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active `CODE_REVIEW-*-G??.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 채팅으로 직접 질문하거나 선택지를 제시하지 않는다. code-review가 사용자 리뷰 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-specific-iop-removal.md`
- Task ids:
  - `inventory`: 활성 파일 기준으로 OTO 전용 잔여 지점을 목록화하고 archive 스냅샷과 무관한 제거 대상을 확정한다.
  - `config-cleanup`: `packages/go/config`, `configs/edge.yaml`, Edge command에서 OTO 전용 agent kind와 bootstrap/release config를 제거한다.
- 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-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-test/local/edge-smoke.md`
- `agent-test/local/testing-smoke.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `packages/go/config/config.go`
- `packages/go/config/config_test.go`
- `configs/edge.yaml`
- `apps/edge/cmd/edge/main.go`
- `apps/edge/cmd/edge/main_test.go`
- `Makefile`

### 테스트 환경 규칙

`test_env=local`이다. `agent-test/local/rules.md`가 있었고 읽었다. Matching profiles는 `agent-test/local/platform-common-smoke.md`, `agent-test/local/edge-smoke.md`, `agent-test/local/testing-smoke.md`다. 적용 명령은 config/package 변경용 `go test ./packages/go/... ./proto/gen/...`, edge 변경용 `go test ./apps/edge/...`, Makefile 확인용 `make test` 계열이다. 이 계획의 focused 검증은 `go test -count=1 ./packages/go/config ./apps/edge/cmd/edge`와 deterministic `rg --sort path`다. 사용자 실행 파이프라인에 닿으므로 후속 전체 검증 계획에서 edge-node/full-cycle 검증 여부를 별도로 다룬다.

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

- `AgentKindOTOAgent` 제거: `packages/go/config/config_test.go`의 agent kind tests와 `apps/edge/cmd/edge/main_test.go` config check tests가 직접 커버한다.
- OTO bootstrap config 제거: 현재 `TestLoadEdge_OTOBootstrap*`와 `TestPatchYAMLUpdatesOTOBootstrapFields`가 반대 계약을 검증하므로 삭제/대체가 필요하다.
- `iop-edge agent register` 제거: 현재 agent register tests가 전용 command 존재를 보증하므로 삭제하고 root/help 테스트가 command 부재를 보증해야 한다.
- full-cycle runtime 검증은 이 plan 단독으로 충분하지 않다. 03 plan에서 최종 검색과 변경 범위 통합 검증을 수행한다.

### 심볼 참조

- `config.AgentKindOTOAgent`: `packages/go/config/config.go`, `packages/go/config/config_test.go`, `apps/edge/cmd/edge/main.go`, `apps/edge/cmd/edge/main_test.go`, `apps/edge/internal/node/*_test.go`, `apps/edge/internal/service/*`, `apps/edge/internal/transport/*`에서 발견했다. 이 plan은 config/CLI 참조만 제거하고 runtime/test 참조는 02 plan으로 넘긴다.
- `OTOBootstrapScriptURL`, `OTOReleaseBaseURL`, `oto_bootstrap_script_url`, `oto_release_base_url`: `packages/go/config/config.go`, `packages/go/config/config_test.go`, `configs/edge.yaml`, `apps/edge/cmd/edge/main.go`, `apps/edge/cmd/edge/main_test.go`에서 발견했다.
- `test-oto-registration-online-smoke`, `OTO_REPO`: `Makefile`에서 발견했고 이 요청 중 즉시 제거되었다.

### 분할 판단

Split decision policy를 계획 파일 선택 전에 평가했다. 이 Milestone은 shared config/API 제거와 broad runtime/test/docs rollout이 섞여 있어 split gate가 적용된다. Shared task group은 `m-oto-specific-iop-removal`이다.

- `01_config_cli_cleanup`: config 계약과 Edge CLI command surface 제거. 선행 없음.
- `02+01_runtime_fixture_cleanup`: transport/service/client/control-plane fixture 정리. `01_config_cli_cleanup`의 `complete.log`가 선행이다. 현재 active/archive predecessor complete.log는 없다.
- `03+01,02_docs_verification`: docs cleanup과 최종 검색/검증. `01`과 `02`의 `complete.log`가 선행이다. 현재 active/archive predecessor complete.log는 없다.

### 범위 결정 근거

이 plan은 `packages/go/config`, `configs/edge.yaml`, `apps/edge/cmd/edge`, `Makefile` 확인까지만 다룬다. Edge transport/service runtime, Control Plane fixture, Client fixture, README/roadmap/agent-ops 문구는 02/03 plan으로 제외한다. `agent-roadmap/archive/**`와 `agent-task/archive/**`는 읽거나 수정하지 않는다.

### 빌드 등급

`local-G06`: 변경 범위가 config/CLI 계약으로 넓지만 deterministic Go tests와 search로 검증 가능하다.

## 구현 체크리스트

- [ ] `packages/go/config`에서 OTO 전용 agent kind와 bootstrap/release config 필드를 제거하고 관련 config tests를 generic-only 계약으로 갱신한다.
- [ ] `configs/edge.yaml`에서 OTO bootstrap fields와 allowed agent kind 문구를 제거한다.
- [ ] `apps/edge/cmd/edge`에서 `agent register` command와 OTO bootstrap YAML patch 경로를 제거하고 root/help/config tests를 갱신한다.
- [ ] `Makefile`의 OTO smoke target 제거 상태를 확인하고 `make -n test`와 `rg --sort path "test-oto-registration-online-smoke|OTO_REPO"` 결과를 review stub에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REFACTOR-1] Config Contract Cleanup

#### 문제

`packages/go/config/config.go:9`-`27`이 `AgentKindOTOAgent = "oto-agent"`를 허용하고, `config.go:86`-`91` 및 `config.go:268`-`273`이 OTO bootstrap/release fields와 defaults를 유지한다. `configs/edge.yaml:14`-`17`와 `configs/edge.yaml:71`-`78`도 같은 전용 설정을 노출한다.

#### 해결 방법

Before:

```go
const (
	AgentKindGenericNode = "generic-node"
	AgentKindOTOAgent    = "oto-agent"
)
...
case AgentKindGenericNode, AgentKindOTOAgent:
	return kind, nil
```

After:

```go
const AgentKindGenericNode = "generic-node"
...
case AgentKindGenericNode:
	return kind, nil
```

`EdgeBootstrapConf`는 `ArtifactBaseURL`, `Listen`, `ArtifactDir`만 남긴다. `TestLoadEdge_OTOBootstrapDefaults`, `TestLoadEdge_OTOBootstrapExplicit`, `TestLoadEdge_NodeAgentKind`의 OTO 허용 expectation을 삭제하거나 invalid-kind rejection으로 바꾼다.

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

- [ ] `packages/go/config/config.go`: `AgentKindOTOAgent`, OTO bootstrap fields/defaults 제거.
- [ ] `packages/go/config/config_test.go`: OTO bootstrap tests 삭제, `oto-agent` 허용 test를 invalid kind test로 흡수.
- [ ] `configs/edge.yaml`: `oto_bootstrap_script_url`, `oto_release_base_url`, allowed values 문구 제거.

#### 테스트 작성

기존 config tests를 갱신한다. 신규 test 이름 후보: `TestLoadEdge_NodeAgentKindRejectsOTOAgent` 또는 기존 `TestLoadEdge_NodeAgentKindInvalid`에 `oto-agent` case 추가.

#### 중간 검증

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

### [REFACTOR-2] Edge CLI OTO Command Cleanup

#### 문제

`apps/edge/cmd/edge/main.go:52`와 `main.go:60`이 `agent register`를 공식 flow 예시로 노출한다. `main.go:824`-`837`, `main.go:888`, `main.go:901`-`1051`, `main.go:1320`-`1367`은 OTO agent command, adapterless OTO exception, OTO bootstrap YAML patch를 구현한다. `apps/edge/cmd/edge/main_test.go:642`-`669`와 `main_test.go:1347`-`1619`가 이 전용 경로를 검증한다.

#### 해결 방법

Before:

```go
root.AddCommand(..., nodeCmd(), nodesCmd(), smokeCmd(), agentCmd())
...
if n.AgentKind != config.AgentKindOTOAgent && !n.Adapters.Ollama.Enabled && !n.Adapters.CLI.Enabled && !n.Adapters.Vllm.Enabled {
	return fmt.Errorf("node %q: at least one adapter must be enabled", name)
}
```

After:

```go
root.AddCommand(..., nodeCmd(), nodesCmd(), smokeCmd())
...
if !n.Adapters.Ollama.Enabled && !n.Adapters.CLI.Enabled && !n.Adapters.Vllm.Enabled {
	return fmt.Errorf("node %q: at least one adapter must be enabled", name)
}
```

`patchYAML`은 `artifact_base_url`만 patch한다. `agentCmd`/`agentRegisterCmd`와 OTO-specific globals/flags/tests를 제거한다. Root/help tests는 `agent` command가 없고 official flow가 `node register`만 안내하는지 확인한다.

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

- [ ] `apps/edge/cmd/edge/main.go`: root help/example, command registration, `agentCmd`, OTO globals, adapterless exception, patch field list 정리.
- [ ] `apps/edge/cmd/edge/main_test.go`: agent register tests 제거, `TestConfigCheckAcceptsOTOAgentWithoutAdapters`를 adapterless node rejection으로 전환, help expectations 갱신.
- [ ] `Makefile`: 이미 제거된 OTO smoke target 잔여 참조 확인만 수행.

#### 테스트 작성

기존 edge cmd tests를 갱신한다. `TestRootCmdIncludesOperationalCommands`에 `agent` 부재 assertion을 추가할 수 있다. `TestConfigCheckRejectsDuplicateNodeTokenAndInvalidConfigs` 또는 별도 test에서 adapterless config rejection을 확인한다.

#### 중간 검증

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

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/go/config/config.go` | REFACTOR-1 |
| `packages/go/config/config_test.go` | REFACTOR-1 |
| `configs/edge.yaml` | REFACTOR-1 |
| `apps/edge/cmd/edge/main.go` | REFACTOR-2 |
| `apps/edge/cmd/edge/main_test.go` | REFACTOR-2 |
| `Makefile` | REFACTOR-2 |

## 최종 검증

```bash
go test -count=1 ./packages/go/config ./apps/edge/cmd/edge
make -n test
rg --sort path -n "AgentKindOTOAgent|OTOBootstrap|OTORelease|oto_bootstrap|oto_release|test-oto-registration-online-smoke|OTO_REPO" packages/go/config configs/edge.yaml apps/edge/cmd/edge Makefile
```

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