# Milestone: 독립 Control Plane 분리 마이그레이션

## 위치

- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/independent-control-plane/PHASE.md`

## 목표

OTO repo를 독립 CI/CD 제품 monorepo로 전환하고, iop에 구현된 OTO 등록/heartbeat/bootstrap 검증 내용을 OTO 전용 Server/Runner 구조로 이관한다.
완료 후 OTO runner는 `apps/runner`에서 단독 실행되고, OTO Server는 `services/core`에서 runner registry와 bootstrap/online 상태를 소유하며, Flutter client는 `apps/client`에서 독립 운영 가능한 콘솔로 동작한다.

## 상태

[완료]

## 승격 조건

- 없음

## 구현 잠금

- 상태: 해제
- 결정 필요: 없음

## 범위

- 현재 루트 OTO Dart CLI/runtime을 `apps/runner`로 이동하고, root entrypoint/test/build helper를 monorepo 기준으로 정리한다.
- Flutter 형식의 독립 client를 `apps/client`에 두고, OTO Server를 제어하는 standalone web/desktop client 기준을 만든다.
- Go 기반 OTO Control Plane backend를 `services/core`에 만들고, runner registry, enrollment token, bootstrap command, heartbeat online 상태를 OTO 책임으로 옮긴다.
- iop/iop2oto에 구현된 OTO agent registration, first heartbeat online, bootstrap command 발급, smoke evidence 구조를 OTO Server/Runner 계약으로 마이그레이션한다.
- runner-server wire 계약은 Go server와 Dart runner/client가 공유할 필요가 생기는 메시지만 `proto/oto`에 둔다.

## 기능

### Epic: [monorepo-boundary] Monorepo 경계 전환

현재 단일 Dart CLI repo를 OTO 제품 monorepo로 재배치하고, 초기 공유 패키지는 만들지 않는 최소 구조를 확정한다.

- [x] [runner-app] 현재 OTO CLI/runtime 소스, 테스트, pubspec, 실행 entrypoint가 `apps/runner` 기준으로 이동되어 기존 로컬 CLI 실행이 유지된다. 검증: `cd apps/runner && dart analyze` 통과, `dart test test/oto_cli_runtime_test.dart test/oto_catalog_cli_test.dart test/oto_validate_cli_test.dart test/oto_application_test.dart test/oto_context_test.dart test/oto_core_test.dart test/oto_system_runtime_test.dart test/oto_command_catalog_test.dart test/oto_command_runtime_test.dart test/oto_scheduler_runtime_test.dart test/oto_agent_config_test.dart test/oto_agent_cli_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_registration_test.dart` 통과.
- [x] [client-app] Flutter client가 `apps/client` 기준으로 추가되고, OTO 독립 콘솔의 source of truth가 client app에 위치한다. 검증: `cd apps/client && flutter analyze`, `flutter test` 통과.
- [x] [core-service] OTO Server backend가 `services/core` 기준으로 생성되고, health/readiness와 local run entrypoint가 준비된다. 검증: `cd services/core && go test ./...` 통과.
- [x] [root-entrypoints] root `Makefile`이 runner/client/core 작업을 위임하도록 정리되어 monorepo root에서 개발 진입점이 명확하다.

### Epic: [iop-extraction] iop OTO 연결 구조 추출

iop의 Edge 구조를 그대로 복제하지 않고, OTO에 필요한 등록/heartbeat/bootstrap 부분만 OTO Server 용어와 책임으로 이관한다.

- [x] [source-map] iop/iop2oto의 OTO 관련 구현 위치가 migration source map으로 정리되어 있다. 포함: config `agent_kind=oto-agent`, bootstrap URL/release URL, `agent register`, transport register handler, first heartbeat online, domain agent summary, smoke target.
- [x] [term-translation] iop 용어가 OTO 용어로 번역되어 있다. 예: Edge -> OTO Server, Node/DomainAgent -> Runner, domain agent summary -> runner status/capability, Edge bootstrap -> runner enrollment/bootstrap.
- [x] [discard-iop-scope] OTO Server로 가져오지 않을 iop 범위가 명시되어 있다. 포함: model serving, OpenAI/A2A routing, generic node adapter, iop control-plane wire, iop client domain-agent panel.
- [x] [migration-tests] 기존 OTO-iop online smoke가 OTO Server 대상 smoke로 전환될 수 있는 테스트 계획과 fixture 경계가 정리되어 있다. 검증: `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_iop_connection_smoke_test.dart` 통과.

### Epic: [server-runner-contract] Server-Runner 연결 계약

OTO Server와 OTO runner가 독립 제품 계약으로 등록, online, capability, job dispatch의 최소 기반을 공유한다.

- [x] [runner-register] runner 등록 요청/응답은 enrollment token뿐 아니라 runner id, alias, protocol version, command catalog/capability summary를 전달할 수 있게 정의된다.
- [x] [online-state] registration accepted와 first heartbeat online 상태가 OTO Server registry에 분리되어 기록되고, heartbeat timeout/disconnect 실패 상태가 정의된다.
- [x] [bootstrap-command] OTO Server가 runner bootstrap command를 발급하고, bootstrap script가 `apps/runner` binary/config를 기준으로 runner를 실행하는 흐름이 정의된다.
- [x] [wire-contract] runner-server 장기 연결에 필요한 protobuf/proto-socket 또는 대체 wire 계약의 원본 위치와 생성물 경로가 확정된다. 검증: Go server와 Dart runner/client가 같은 계약을 기준으로 빌드 가능하다.

### Epic: [product-boundary] 제품 책임 경계 정리

OTO, iop, NomadCode의 소비 관계를 분리해 OTO가 독립 CI/CD 제품으로 유지되도록 한다.

- [x] [oto-owns-cicd] OTO Server는 CI/CD runner registry, job, execution history, log/artifact 상태를 소유하고, iop Edge나 iop Control Plane을 전제로 하지 않는다.
- [x] [iop-ai-provider] iop는 AI agent/model/provider 기능이 필요할 때만 선택적으로 호출하는 외부 provider로 정의되고, OTO runner 연결의 기본 경로에서 제외된다.
- [x] [nomadcode-consumer] NomadCode는 OTO Server API를 소비하는 host 제품으로 정리되고, OTO client/server 구현을 native module로 복제하지 않는다.
- [x] [downstream-roadmap] 기존 `edge-direct-oto-agent`와 `message-based-build-agent` Phase/Milestone이 새 독립 OTO Server 방향에 맞게 후속 갱신 대상인지 정리된다.

## 완료 리뷰

- 상태: 승인됨
- 요청일: 2026-06-06
- 완료 근거: monorepo scaffold, iop 추출 계획, runner-server wire 계약, runner 등록/online/bootstrap command, downstream roadmap 정리가 완료되었다. `05+04_core_cicd_state`, `06+05_runner_dispatch_contract`, `07+05,06_cicd_smoke_evidence` PASS 완료 근거로 OTO Server job/execution/log/artifact 책임 범위도 충족되었다. `07+05,06_cicd_smoke_evidence/complete.log`의 Roadmap Completion이 `oto-owns-cicd` 완료를 기록한다.
- 리뷰 필요:
  - [x] 사용자가 완료 결과를 확인했다
  - [x] archive 이동을 승인했다
- 리뷰 코멘트: 사용자 요청으로 현 Milestone을 종료하고 다음 Milestone으로 전환한다.

## 범위 제외

- OTO Server의 전체 job scheduling policy, artifact storage 운영 정책, 장기 권한/감사 모델을 완성하지 않는다.
- Jenkins 전체 기능을 한 번에 대체하지 않는다.
- iop native module 또는 iop Edge domain agent로 OTO를 연결하는 경로를 새 기본 경로로 유지하지 않는다.
- 초기 전환 단계에서 `packages/` 공유 패키지를 만들지 않는다. 둘 이상의 runtime이 실제 import해야 하는 코드가 생길 때만 후속으로 분리한다.
- AI 기반 pipeline 생성, 실패 분석, command 추천은 iop provider 연동 후속 작업으로 둔다.

## 작업 컨텍스트

- 관련 경로: `lib/**`, `test/**`, `assets/script/shell/oto_agent_bootstrap.sh`, `pubspec.yaml`
- 신규 경로: `apps/runner/`, `apps/client/`, `services/core/`, `proto/oto/`
- migration source: `../iop/apps/edge/internal/transport/server.go`, `../iop/apps/edge/internal/node/**`, `../iop/apps/edge/internal/service/service.go`, `../iop/apps/edge/cmd/edge/main.go`, `../iop/packages/go/config/config.go`, `../iop/Makefile`, `../iop/proto/iop/runtime.proto`
- 표준선(선택): OTO runner는 서버 없이도 로컬 typed-command CI/CD runtime으로 유지한다.
- 표준선(선택): OTO Server 연결은 중앙 registry, web control plane, 원격 job/log/artifact 관리가 필요할 때 사용하는 선택 경로다.
- 표준선(선택): `apps/runner`, `apps/client`, `services/core`를 먼저 만들고, 공유 코드는 실제 중복 import 수요가 생기기 전까지 `packages/`로 빼지 않는다.
- 표준선(선택): runner-server wire가 proto-socket 장기 연결을 유지한다면 원본 계약은 `proto/oto`에 둔다. HTTP/JSON만으로 충분한 client-core 표면은 `services/core` API 문서 또는 후속 contracts 경계에서 정리한다.
- 폐기된 경로: `agent-roadmap/archive/phase/edge-direct-oto-agent/PHASE.md`와 `agent-roadmap/archive/phase/edge-direct-oto-agent/milestones/oto-agent-registration.md`는 iop Edge 직접 연결 기본 경로로는 폐기되었고, migration source/evidence로만 참조한다.
- 선행 작업: OTO-iop proto-socket 통신 기반, Edge bootstrap 계약, `oto-agent` 등록 흐름의 검증 근거
- 후속 작업: OTO Server job dispatch, log streaming, artifact reporting, typed command catalog remote execution, iop AI provider integration
- 확인 필요: 기존 iop 직접 연결 Phase를 완료/보류/폐기 중 어떤 상태로 정리할지는 이 Milestone의 `downstream-roadmap` Task에서 판단한다.
- 동기화 근거(2026-06-05): `apps/runner`, `apps/client`, `services/core`, root `Makefile`이 존재하고 runner/client/core 기본 검증이 통과했다. `apps/runner/test/oto_agent_migration_plan_test.dart`가 legacy iop smoke와 future OTO Server smoke의 fixture 경계를 정리했고, `apps/runner/test/oto_iop_connection_smoke_test.dart`는 migration source evidence로 유지한다. `proto/oto/runner.proto`와 Go/Dart 생성물이 추가되어 `make proto`, `cd services/core && go test ./...`, `cd apps/runner && dart analyze`가 통과했다. `agent-task/archive/2026/06/m-control-plane-separation-migration/02+01_runner_registration/complete.log`, `03+02_online_state/complete.log`, `04+02_bootstrap_command/complete.log`의 Roadmap Completion 근거로 `runner-register`, `online-state`, `bootstrap-command`를 완료 처리했다. `edge-direct-oto-agent`는 폐기 archive로 유지하고 `message-based-build-agent`는 독립 OTO Server/Runner 후속 Phase로 갱신해 `downstream-roadmap`을 완료 처리했다. 단, OTO Server job/execution/log/artifact 책임 범위는 아직 남아 있어 Milestone은 `[진행중]`으로 유지한다.
- 작업 상태 동기화(2026-06-05): `downstream-roadmap`은 문서 정리로 즉시 완료했고, `oto-owns-cicd`는 큰 구현 작업이라 `agent-task/m-control-plane-separation-migration/05+04_core_cicd_state`, `06+05_runner_dispatch_contract`, `07+05,06_cicd_smoke_evidence` split plan으로 남겼다. workspace lock 확인 결과 이 Milestone과 관련된 외부 잠금은 없다.
- 작업 상태 동기화(2026-06-06): `agent-task/archive/2026/06/m-control-plane-separation-migration/05+04_core_cicd_state/complete.log`, `06+05_runner_dispatch_contract/complete.log`, `07+05,06_cicd_smoke_evidence/complete.log`가 모두 PASS로 정리되었다. `07+05,06_cicd_smoke_evidence/complete.log`의 Roadmap Completion 근거로 `oto-owns-cicd`를 완료 처리했고, 모든 기능 Task가 `[x]`가 되어 Milestone을 `[검토중]`으로 전환했다. workspace lock 확인 결과 이 Milestone과 관련된 외부 잠금은 없다.
