docs(roadmap): OTO agent registry 계획을 정리한다

Automation Runtime과 Bridge 확장 phase를 진행중으로 전환하고 OTO Agent Registry 구현 milestone과 split plan을 활성 작업으로 연결한다.
This commit is contained in:
toki 2026-06-03 12:23:03 +09:00
parent e4c645a8d7
commit 4df9cc8872
14 changed files with 1228 additions and 41 deletions

View file

@ -33,9 +33,9 @@ RAG, context 구성/압축, web search, MCP 정책, tool policy, output validati
- 경로: `agent-roadmap/phase/inference-provider-extension/PHASE.md`
- 요약: Ollama 경로가 안정화된 뒤 그 결과를 기준선으로 삼아 SGLang 같은 추가 추론 서버 provider를 붙이고, provider별 adapter/config/target/model 매핑 표준선을 정리하는 단계다.
- [계획] Automation Runtime과 Bridge 확장
- [진행중] Automation Runtime과 Bridge 확장
- 경로: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- 요약: Runtime과 Automation 실행 흐름을 공통화하고, agent 설치형/비설치형 대상 제어 경로를 분리해 확장하는 단계다.
- 요약: Runtime과 Automation 실행 흐름을 공통화하고, OTO 같은 specialized domain agent의 Edge 직접 연결, bootstrap/enrollment, message boundary와 agentless remote terminal bridge를 분리해 확장하는 단계다.
- [진행중] Control Plane과 Client 운영
- 경로: `agent-roadmap/phase/control-plane-portal-ops/PHASE.md`

View file

@ -9,25 +9,24 @@
Edge가 specialized domain agent를 생성하고 bootstrap command를 발급해 대상 머신에서 agent 설치와 등록을 완료하는 enrollment 흐름을 설계한다.
OTO는 build/deploy domain agent의 대표 후보로 둔다.
이 Milestone은 OTO 연동 전체 구현을 한 번에 담지 않고, iop2oto 브랜치에서 이어서 구현할 registry, bootstrap command, online smoke, message boundary Milestone의 계약 경계를 확정한다.
## 상태
[계획]
[완료]
## 구현 잠금
- 상태: 잠금
- 결정 필요: 아래 체크리스트
- [ ] iop MVP에서 `enrollment_token`을 1회성 토큰으로만 볼지, 등록 후 장기 credential 재발급까지 같은 Milestone에 포함할지 결정한다.
- [ ] HTTP local/insecure bootstrap 모드를 MVP에서 허용할지, 허용한다면 Edge fingerprint/public key pinning과 checksum/signature 중 무엇을 필수 조건으로 둘지 결정한다.
- 상태: 해제
- 결정 필요: 없음
## 범위
- Edge agent registry를 generic node와 specialized domain agent를 함께 다룰 수 있는 모델로 확장
- agent type별 bootstrap command 발급 표면 설계
- one-time bootstrap token, Edge fingerprint/public key pinning, checksum/signature 검증 계약
- 등록 후 장기 credential 재발급 흐름
- OTO agent의 build run, cancel, status, capability, artifact, log event 메시지 경계
- Edge agent registry를 generic node와 specialized domain agent를 함께 다룰 수 있는 모델로 확장하는 구현 Milestone 경계 정의
- agent type별 bootstrap command 발급 표면 설계와 OTO 전용 command 구현 Milestone 분리
- MVP enrollment token은 1회성 등록 토큰으로 두고, 등록 후 장기 credential 재발급은 후속 보안 강화로 분리
- HTTP local/insecure bootstrap은 명시적 local/dev 모드에서만 허용하고, 운영 기본값은 HTTPS bootstrap/release URL로 둔다
- OTO agent의 build run, cancel, status, capability, artifact, log event 메시지 경계를 후속 message boundary Milestone으로 분리
- OTO가 확정한 Linux MVP bootstrap command, release asset, config path, background 실행 기준을 Edge bootstrap 발급 계약으로 수용
- Edge가 OTO agent 생성, command 발급, registration accepted, 최초 heartbeat 기반 online 상태를 구분해 표현하는 기준 정리
@ -35,33 +34,34 @@ OTO는 build/deploy domain agent의 대표 후보로 둔다.
### Epic: [agent-boundary] Agent Boundary and Enrollment Path
- [ ] [direct-agent] OTO agent는 `iop-node` 하위 프로세스가 아니라 Edge에 직접 outbound 연결하는 specialized domain agent로 둔다.
- [ ] [bootstrap-first] Agent를 설치할 수 있는 대상은 bootstrap/enrollment를 우선한다.
- [ ] [bridge-split] Agent 설치가 어렵거나 일회성 유지보수 대상이면 remote terminal bridge 경로와 구분한다.
- [x] [direct-agent] OTO agent는 `iop-node` 하위 프로세스가 아니라 Edge에 직접 outbound 연결하는 specialized domain agent로 둔다.
- [x] [bootstrap-first] Agent를 설치할 수 있는 대상은 bootstrap/enrollment를 우선한다.
- [x] [bridge-split] Agent 설치가 어렵거나 일회성 유지보수 대상이면 remote terminal bridge 경로와 구분한다.
### Epic: [bootstrap-command] Bootstrap Command Contract
- [ ] [bootstrap-command] Edge가 OTO agent 생성과 bootstrap command 발급 상태를 표현하고 Linux 대상에서 바로 실행할 one-line bootstrap command를 발급하는 계약이 정의되어 있다.
- [ ] [agent-record] Edge-side agent record가 `agent_kind=oto-agent`, agent id, alias, enrollment token, bootstrap 발급 상태를 소유하는 기준이 정의되어 있다.
- [ ] [oto-contract] OTO의 bootstrap script 인자, release asset 이름, config path, background 실행 기준이 iop Edge 발급 계약에 반영되어 있고 OTO 로드맵 계약과 충돌하지 않는다.
- [ ] [registration-state] bootstrap command 실행 후 agent config/service 등록과 Edge outbound enrollment 흐름이 문서화되고, `bootstrap issued`, `registration accepted`, `first heartbeat received`, `online`, `failed` 상태 기준이 구분되어 있다.
- [ ] [insecure-policy] HTTP local/insecure bootstrap 모드는 명시 선택과 추가 검증 조건을 요구한다.
- [x] [bootstrap-command] Edge가 OTO agent 생성과 bootstrap command 발급 상태를 표현하고 Linux 대상에서 바로 실행할 one-line bootstrap command를 발급하는 계약이 정의되어 있다.
- [x] [agent-record] Edge-side agent record가 `agent_kind=oto-agent`, agent id, alias, enrollment token, bootstrap 발급 상태를 소유하는 기준이 정의되어 있다.
- [x] [oto-contract] OTO의 bootstrap script 인자, release asset 이름, config path, background 실행 기준이 iop Edge 발급 계약에 반영되어 있고 OTO 로드맵 계약과 충돌하지 않는다.
- [x] [registration-state] bootstrap command 실행 후 agent config/service 등록과 Edge outbound enrollment 흐름이 문서화되고, `bootstrap issued`, `registration accepted`, `first heartbeat received`, `online`, `failed` 상태 기준이 구분되어 있다.
- [x] [insecure-policy] HTTP local/insecure bootstrap 모드는 명시 선택과 추가 검증 조건을 요구한다.
- [x] [milestone-split] registry 구현, bootstrap command 발급, online smoke, message boundary가 iop2oto Phase 안의 후속 Milestone으로 분리되어 있다.
### Epic: [ownership-boundary] IOP and OTO Ownership
- [ ] [ownership] OTO agent와 generic Node의 책임 경계가 registry와 protocol 수준에서 구분되고 iop와 OTO의 책임 경계가 문서화되어 있다.
- [ ] [iop-ownership] iop는 Edge agent registry, bootstrap command 발급, credential, 보안 검증 기준을 소유한다.
- [ ] [oto-ownership] OTO는 build/deploy domain agent의 설치 산출물, 설정 생성, YAML run/capability/event 의미를 소유하고, OTO의 Edge bootstrap 계약 문서는 이 Milestone 산출물을 참조해 재개 가능하다.
- [x] [ownership] OTO agent와 generic Node의 책임 경계가 registry와 protocol 수준에서 구분되고 iop와 OTO의 책임 경계가 문서화되어 있다.
- [x] [iop-ownership] iop는 Edge agent registry, bootstrap command 발급, credential, 보안 검증 기준을 소유한다.
- [x] [oto-ownership] OTO는 build/deploy domain agent의 설치 산출물, 설정 생성, YAML run/capability/event 의미를 소유하고, OTO의 Edge bootstrap 계약 문서는 이 Milestone 산출물을 참조해 재개 가능하다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 모든 기능 Task가 아직 충족되지 않았다.
- 상태: 승인됨
- 요청일: 2026-06-03
- 완료 근거: OTO direct agent 경계, bootstrap/enrollment 우선 경로, OTO bootstrap command/record/state 기준, insecure policy, iop/OTO ownership이 현재 Milestone 문서와 후속 구현 Milestone으로 정리되었다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
- [x] 사용자가 완료 결과를 확인했다
- [x] archive 이동을 승인했다
- 리뷰 코멘트: 2026-06-03 사용자 요청으로 현재 마일스톤을 종료하고 archive 이동한다.
## 범위 제외
@ -70,13 +70,16 @@ OTO는 build/deploy domain agent의 대표 후보로 둔다.
- bootstrap 보안 검증을 생략한 insecure 기본값
- OTO의 Linux bootstrap script 구현 자체
- OTO의 YAML run/capability/artifact/log 메시지 전체 구현
- Edge registry/API/DB schema의 전체 운영 영속화
- OTO와 iop 양쪽 repo의 모든 구현을 같은 Milestone에서 완료 처리
## 작업 컨텍스트
- 관련 경로: `apps/edge`, `README.md`, `agent-test/local/testing-smoke.md`, `../oto/agent-roadmap/phase/edge-direct-oto-agent/milestones/oto-agent-registration.md`, `../oto/agent-roadmap/phase/message-based-build-agent/milestones/agent-message-protocol.md`, `../oto/assets/script/shell/oto_agent_bootstrap.sh`
- 전환 상태: Ollama 실테스트와 후속 안정화를 우선 열어두는 동안 이 마일스톤은 계획 후보로 대기한다. 구현 시작 전 `enrollment_token` 범위와 HTTP local/insecure bootstrap 정책 결정을 먼저 해소한다.
- 전환 상태: iop2oto 브랜치에서는 OTO 연동 작업을 이 Phase 아래에서 이어가며, OTO repo 로드맵에는 iop 구현 결과를 소비하는 후속 계약만 남긴다.
- 표준선(선택): OTO agent는 `iop-node` 하위 프로세스가 아니라 Edge에 직접 outbound 연결하는 specialized domain agent로 둔다.
- 표준선(선택): Edge는 `oto-agent` record를 만들고, agent id/alias/enrollment token/release base URL/bootstrap script URL을 포함한 one-line command를 발급한다.
- 표준선(선택): `enrollment_token`은 MVP에서 1회성 등록 토큰으로 다루고, 장기 credential 재발급/rotation은 후속 보안 강화 Milestone 후보로 둔다.
- 표준선(선택): OTO Linux MVP command 형식은 `curl -fsSL "${OTO_BOOTSTRAP_URL}" | bash -s -- --edge-url "${EDGE_URL}" --agent-id "${AGENT_ID}" --enrollment-token "${ENROLLMENT_TOKEN}" --release-base-url "${OTO_RELEASE_BASE_URL}" --agent-alias "${AGENT_ALIAS}"`를 기준으로 한다.
- 표준선(선택): OTO bootstrap 필수 인자는 `--edge-url`, `--agent-id`, `--enrollment-token`, `--release-base-url`이고, 선택 인자는 `--agent-alias`, `--install-dir`, `--config-path`, `--workspace-root`, `--log-dir`, `--no-background`다.
- 표준선(선택): OTO Linux release asset은 `uname -m` 기준으로 `oto-linux-x64.tar.gz` 또는 `oto-linux-arm64.tar.gz`를 선택하며, archive 안에는 실행 파일 `oto`가 있어야 한다.
@ -85,5 +88,5 @@ OTO는 build/deploy domain agent의 대표 후보로 둔다.
- 표준선(선택): OTO MVP 보안은 HTTPS bootstrap/release URL, token 재출력 금지, 설정 파일 권한 제한, 임시 파일 정리를 기본으로 두고 checksum/signature, Edge fingerprint pinning, credential rotation은 후속 강화로 둔다.
- 전달 계약: iop는 OTO script 구현을 복제하지 않고, Edge가 발급하는 bootstrap command와 registry/credential/state 모델이 OTO 계약을 소비하도록 문서화한다.
- 선행 작업: Edge-Node 실행 스켈레톤, Edge 입력 표면, Specialized Agent proto-socket 연결 기반
- 후속 작업: OTO `oto-agent` 등록 흐름, agent 메시지 프로토콜, OTO YAML run/capability/event 메시지 경계
- 확인 필요: enrollment token의 만료/재사용/장기 credential 전환 정책, local/insecure bootstrap 허용 여부와 추가 검증 조건
- 후속 작업: OTO Agent Registry 구현, OTO Bootstrap Command 발급, OTO Registration Online Smoke, OTO Agent Message Boundary
- 확인 필요: OTO release asset 실제 배포 URL과 iop local/dev smoke에서 사용할 포트/host 값

View file

@ -2,14 +2,14 @@
## 활성 Phase
- [진행중] Control Plane과 Client 운영
- 경로: `agent-roadmap/phase/control-plane-portal-ops/PHASE.md`
- [진행중] Automation Runtime과 Bridge 확장
- 경로: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
## 활성 Milestone
- [진행중] Control Plane과 Client
- Phase: `agent-roadmap/phase/control-plane-portal-ops/PHASE.md`
- 경로: `agent-roadmap/phase/control-plane-portal-ops/milestones/control-plane-client.md`
- [진행중] OTO Agent Registry 구현
- Phase: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
## 선택 규칙

View file

@ -2,7 +2,7 @@
## 상태
[계획]
[진행중]
## 목표
@ -18,13 +18,29 @@ CLI 실행, specialized agent 등록, bootstrap/enrollment, 원격 터미널 브
- 경로: `agent-roadmap/archive/phase/automation-runtime-bridge/milestones/cli-automation-runtime-stabilization.md`
- 요약: one-shot, persistent terminal, opencode SSE, codex exec 계열 CLI 실행 모드와 운영 command 응답을 같은 adapter execution 모델 안에서 안정화했다.
- [완료] Agent Bootstrap과 OTO 등록
- 경로: `agent-roadmap/archive/phase/automation-runtime-bridge/milestones/agent-bootstrap-oto-enrollment.md`
- 요약: OTO를 Edge 직접 연결 specialized domain agent로 등록하기 위한 MVP enrollment 계약과 후속 구현 Milestone 경계를 확정했다.
- [검토중] Specialized Agent proto-socket 연결 기반
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/specialized-agent-proto-socket-foundation.md`
- 요약: OTO의 node-compatible proto-socket registration smoke를 바탕으로 Edge의 specialized agent kind, registry/config, message boundary, reconnect 정책과 runtime 경로 구분을 완료 후보로 정리했다.
- [계획] Agent Bootstrap과 OTO 등록
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-bootstrap-oto-enrollment.md`
- 요약: specialized domain agent의 bootstrap command 발급, 설치, 등록, 장기 credential 흐름을 설계한다.
- [진행중] OTO Agent Registry 구현
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
- 요약: Config/Store, Registry/Transport, Service Snapshot 3개 active plan으로 나누어 Edge-side `generic-node`/`oto-agent` 구분 구현을 진행한다.
- [계획] OTO Bootstrap Command 발급
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-bootstrap-command-issue.md`
- 요약: `iop-edge`가 OTO agent record를 만들고 OTO Linux bootstrap script가 소비할 one-line command를 발급하는 CLI/config 표면을 구현한다.
- [계획] OTO Registration Online Smoke
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-registration-online-smoke.md`
- 요약: OTO Dart `proto_socket` client와 iop Edge를 함께 띄워 registration accepted, 최초 heartbeat, online/failed 상태 구분을 검증한다.
- [계획] OTO Agent Message Boundary
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-message-boundary.md`
- 요약: registration 이후 build run, cancel, status, capability, artifact, log event를 Node adapter stream과 분리된 OTO domain payload 후보로 정리한다.
- [계획] 원격 터미널 브리지 POC
- 경로: `agent-roadmap/phase/automation-runtime-bridge/milestones/remote-terminal-bridge-poc.md`

View file

@ -0,0 +1,64 @@
# Milestone: OTO Agent Message Boundary
## 위치
- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
## 목표
OTO registration 이후 Edge가 OTO agent에 보낼 build/deploy domain 메시지 경계를 정한다.
기존 `RunRequest/RunEvent`, `CancelRequest`, `NodeCommandRequest/Response`는 envelope 재사용 범위를 정하고, OTO 전용 capability, artifact, log, progress, build result payload는 Node adapter stream과 분리한다.
## 상태
[계획]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- OTO build run, cancel, status, capability, artifact, log event의 최소 메시지 경계를 정의한다.
- generic node adapter execution과 OTO domain run의 공통 envelope/전용 payload 분리 기준을 정한다.
- proto schema 변경이 필요한 경우 원본 `proto/iop/*.proto`와 생성물 갱신 범위를 명확히 한다.
- OTO YAML pipeline 의미와 iop Edge routing/audit 의미의 소유 경계를 문서화한다.
## 기능
### Epic: [domain-payload] OTO Domain Payload Boundary
OTO 전용 build/deploy 메시지와 기존 Node 메시지의 재사용 범위를 분리한다.
- [ ] [run-envelope] OTO build run이 기존 run envelope를 재사용할지, 전용 request를 둘지 판단 기준이 문서화되어 있다.
- [ ] [capability-status] OTO capability와 status 조회 메시지의 최소 필드가 정리되어 있다.
- [ ] [artifact-log] artifact, log, progress, build result event가 Node adapter stream과 충돌하지 않는 payload 후보로 정리되어 있다.
- [ ] [proto-scope] proto schema 변경이 필요한 파일과 생성물 갱신 명령이 정리되어 있다. 검증: schema 변경이 있다면 `make proto`와 대상 Go test 기준이 함께 기록된다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 모든 기능 Task가 아직 충족되지 않았다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- OTO YAML pipeline 실행 엔진 구현
- artifact storage 전체 설계
- Control Plane UI와 multi-edge fleet scheduling
- self-update와 credential rotation
## 작업 컨텍스트
- 관련 경로: `proto/iop/runtime.proto`, `proto/iop/job.proto`, `apps/edge/internal/service`, `apps/edge/internal/events`, `../oto/agent-roadmap/phase/message-based-build-agent/milestones/agent-message-protocol.md`
- 표준선(선택): registration/heartbeat는 기존 proto-socket 흐름을 유지하고, build/deploy 의미는 필요할 때 전용 typed payload로 분리한다.
- 표준선(선택): OTO는 YAML run/capability/event 의미를 소유하고, iop는 Edge routing, command relay, lifecycle/audit boundary를 소유한다.
- 선행 작업: OTO Registration Online Smoke
- 후속 작업: Control Plane multi-edge operations에서 OTO/build-deploy domain agent 상태 노출 여부 결정
- 확인 필요: OTO의 첫 MVP run payload가 YAML 파일 경로 실행인지, 사전 등록된 pipeline id 실행인지

View file

@ -0,0 +1,69 @@
# Milestone: OTO Agent Registry 구현
## 위치
- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
## 목표
Edge-side registration record와 connected registry가 generic `iop-node``oto-agent`를 구분하도록 구현한다.
기존 `RegisterRequest(token)` handshake는 유지하되 token이 가리키는 record에서 `agent_kind=oto-agent`를 판별하고 lifecycle/capability 표시의 기반을 만든다.
## 상태
[진행중]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- Edge config와 in-memory store에 generic node와 OTO agent record를 구분하는 최소 모델을 추가한다.
- 기존 `nodes[]` 기반 generic node 등록 경로와 호환성을 유지한다.
- connected entry에 agent kind, alias, id, lifecycle state, optional capability summary를 보존할 수 있는 구조를 만든다.
- duplicate connection과 reconnect 정책은 기존 reject 기본값을 유지하고, replace 허용은 후속 감사/close reason 정의 뒤로 미룬다.
## 기능
### Epic: [registry-model] Agent Registry Model
Edge가 token으로 찾은 record를 generic node 또는 OTO agent로 분류하고 연결 상태를 구분한다.
- [ ] [agent-kind-model] Edge-side registration record가 `generic-node``oto-agent` kind를 표현한다.
- [ ] [compat-node] 기존 `nodes[]``iop-node` 등록 테스트가 agent kind 추가 뒤에도 깨지지 않는다. 검증: `go test ./apps/edge/internal/node ./apps/edge/internal/transport ./apps/edge/cmd/edge`
- [ ] [connected-entry] connected registry entry가 agent id, alias, kind, lifecycle state를 노출할 수 있다.
- [ ] [duplicate-policy] 같은 OTO agent identity의 중복 연결은 기본 reject로 처리되고 reason이 구분된다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: active implementation plan을 생성했으며 모든 기능 Task는 아직 충족되지 않았다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- 장기 credential rotation 구현
- OTO build/deploy run payload 구현
- Control Plane fleet 화면 구현
- DB 영속화와 audit schema 확정
## 작업 컨텍스트
- 관련 경로: `packages/go/config`, `apps/edge/internal/node`, `apps/edge/internal/transport`, `apps/edge/internal/service`, `configs/edge.yaml`
- Active task group: `agent-task/m-oto-agent-registry-implementation/`
- Active plan 분할:
- `01_config_store`: `agent-kind-model` 구현 계획. Config/NodeStore에 `generic-node`, `oto-agent` kind 모델을 추가한다.
- `02+01_registry_transport`: `connected-entry`, `duplicate-policy` 구현 계획. Registry entry와 transport registration 경로에 kind/lifecycle과 OTO duplicate reason을 반영한다.
- `03+01,02_service_snapshots`: `compat-node` 구현 계획. Service snapshot에 kind/lifecycle을 노출하고 기존 generic node 회귀를 검증한다.
- 표준선(선택): `RegisterRequest`에는 kind field를 추가하지 않고, token이 가리키는 Edge-side record에서 kind를 판별한다.
- 표준선(선택): registry는 먼저 기존 `NodeEntry` 확장 또는 얇은 `AgentEntry` 도입 중 가장 작은 변경으로 시작한다.
- 선행 작업: Agent Bootstrap과 OTO 등록, Specialized Agent proto-socket 연결 기반
- 후속 작업: OTO Bootstrap Command 발급, OTO Registration Online Smoke
- 확인 필요: Control Plane에 노출할 agent kind/status 필드 이름은 Control Plane wire 갱신 시 재확인한다.

View file

@ -0,0 +1,64 @@
# Milestone: OTO Bootstrap Command 발급
## 위치
- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
## 목표
`iop-edge`가 OTO agent record를 생성하고 대상 Linux host에서 바로 실행할 one-line bootstrap command를 발급한다.
Edge는 OTO bootstrap script를 구현하지 않고, OTO가 소유한 script 인자와 release asset 계약을 소비하는 command를 만든다.
## 상태
[계획]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- `iop-edge` CLI에 OTO agent registration 또는 agent bootstrap command 발급 표면을 추가한다.
- Edge config에 OTO agent id, alias, enrollment token, release base URL, bootstrap script URL을 기록하거나 재생성 가능한 구조를 둔다.
- 출력 command는 OTO Linux MVP bootstrap 인자와 일치해야 한다.
- local/dev HTTP bootstrap은 명시 flag가 있을 때만 허용하고, 기본 출력은 HTTPS URL을 우선한다.
## 기능
### Epic: [command-surface] Edge CLI Command Surface
Edge-local field UX에서 OTO agent를 생성하고 bootstrap command를 출력한다.
- [ ] [agent-register-cmd] `iop-edge`가 OTO agent record를 만들거나 갱신하는 command 표면을 제공한다.
- [ ] [bootstrap-output] command 출력은 한 줄 bootstrap command만 안정적으로 제공하고 token을 불필요하게 재출력하지 않는다.
- [ ] [oto-args] 출력 command가 OTO bootstrap 필수 인자 `--edge-url`, `--agent-id`, `--enrollment-token`, `--release-base-url`을 포함한다.
- [ ] [config-roundtrip] 생성된 edge config를 `config check`와 runtime load가 읽을 수 있다. 검증: `go test ./apps/edge/cmd/edge ./packages/go/config`
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 모든 기능 Task가 아직 충족되지 않았다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- OTO bootstrap script 자체 구현
- OTO release asset 빌드/업로드 자동화
- checksum/signature 강제 검증
- Control Plane 원격 발급 UI
## 작업 컨텍스트
- 관련 경로: `apps/edge/cmd/edge/main.go`, `packages/go/config`, `configs/edge.yaml`, `../oto/assets/script/shell/oto_agent_bootstrap.sh`
- 표준선(선택): command 형식은 `curl -fsSL "${OTO_BOOTSTRAP_URL}" | bash -s -- --edge-url "${EDGE_URL}" --agent-id "${AGENT_ID}" --enrollment-token "${ENROLLMENT_TOKEN}" --release-base-url "${OTO_RELEASE_BASE_URL}" --agent-alias "${AGENT_ALIAS}"`를 기준으로 한다.
- 표준선(선택): MVP에서는 one-time enrollment token을 사용하고 장기 credential 재발급은 후속으로 둔다.
- 선행 작업: OTO Agent Registry 구현
- 후속 작업: OTO Registration Online Smoke
- 확인 필요: local smoke에서 사용할 OTO bootstrap script URL과 release base URL 기본값

View file

@ -0,0 +1,64 @@
# Milestone: OTO Registration Online Smoke
## 위치
- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
## 목표
iop Edge와 OTO `oto-agent`를 실제로 함께 띄워 Edge 직접 outbound 등록 흐름을 검증한다.
완료 시점에는 `registration accepted`와 최초 heartbeat 도착을 모두 만족했을 때만 online으로 보는 기준이 iop 구현과 OTO smoke에서 확인되어야 한다.
## 상태
[계획]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- OTO Dart `proto_socket` client가 iop Edge의 OTO agent record token으로 등록되는 smoke를 구성한다.
- Edge는 registration accepted, first heartbeat received, online, failed 상태를 구분할 수 있어야 한다.
- unknown token, duplicate connection, heartbeat timeout, bootstrap command 실행 실패 또는 등록 실패를 구분해 진단 가능한 reason을 남긴다.
- OTO repo의 `oto-agent` 등록 흐름 잠금 해제 근거로 사용할 수 있는 최소 E2E evidence를 만든다.
## 기능
### Epic: [online-state] Registration and Online State
Edge와 OTO가 같은 기준으로 online/failed 상태를 판정한다.
- [ ] [accepted-state] OTO agent registration accepted 상태가 generic node와 구분되어 기록된다.
- [ ] [heartbeat-online] 최초 heartbeat 도착 후 online으로 전환된다. 검증: OTO Dart smoke 또는 통합 smoke에서 registration accepted 뒤 heartbeat 도착까지 확인한다.
- [ ] [failure-reason] unknown token, duplicate connection, heartbeat timeout이 서로 다른 실패 reason으로 확인된다.
- [ ] [unlock-evidence] OTO `oto-agent` 등록 흐름 잠금 해제에 사용할 smoke 결과와 실행 명령이 문서 또는 test log에 남는다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 모든 기능 Task가 아직 충족되지 않았다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- build/deploy run payload 전체
- artifact/log stream 전체
- 장기 credential rotation
- Control Plane fleet UI 반영
## 작업 컨텍스트
- 관련 경로: `apps/edge/internal/transport`, `apps/edge/internal/node`, `apps/edge/internal/events`, `scripts/e2e-*.sh`, `../oto/test/oto_iop_connection_smoke_test.dart`
- 표준선(선택): online 판정은 Edge registration accepted와 최초 heartbeat 도착을 모두 만족했을 때로 둔다.
- 표준선(선택): heartbeat timeout은 transport close reason과 lifecycle event metadata로 남긴다.
- 선행 작업: OTO Agent Registry 구현, OTO Bootstrap Command 발급
- 후속 작업: OTO Agent Message Boundary, OTO repo `oto-agent` 등록 흐름 잠금 해제 검토
- 확인 필요: smoke 실행 시 iop Edge와 OTO를 같은 host에서 띄울지, split host로 띄울지

View file

@ -0,0 +1,132 @@
<!-- task=m-oto-agent-registry-implementation/01_config_store plan=0 tag=OAR01 -->
# Code Review Reference - OAR01
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-06-03
task=m-oto-agent-registry-implementation/01_config_store, plan=0, tag=OAR01
## Roadmap Targets
- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
- Task ids:
- `agent-kind-model`: Node/Agent 등록 record가 `generic-node``oto-agent`를 구분한다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
1. 판정을 append한다.
2. `CODE_REVIEW-local-G06.md``code_review_local_G06_N.log`, `PLAN-local-G06.md``plan_local_G06_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-oto-agent-registry-implementation/01_config_store/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [OAR01-1] Config agent kind | [ ] |
| [OAR01-2] NodeStore record kind | [ ] |
## 구현 체크리스트
- [ ] `packages/go/config/config.go`에 agent kind 상수와 `NodeDefinition.AgentKind`를 추가하고 `LoadEdge` 정규화/검증을 구현한다.
- [ ] `apps/edge/internal/node/store.go``NodeRecord``LoadFromConfig`에 agent kind 보존 및 기본값 처리를 추가한다.
- [ ] `packages/go/config/config_test.go``apps/edge/internal/node/store_test.go`에 kind 로딩, 기본값, invalid kind, 중복 정책 회귀 테스트를 추가한다.
- [ ] 중간 및 최종 검증 명령을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_local_G06_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_local_G06_M.log`로 아카이브한다.
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md``agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-oto-agent-registry-implementation/01_config_store/``agent-task/archive/YYYY/MM/m-oto-agent-registry-implementation/01_config_store/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-oto-agent-registry-implementation/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-local-G06.md``CODE_REVIEW-local-G06.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- `agent_kind` 빈 값이 `generic-node`로 정규화되는지 확인한다.
- invalid kind가 설정 로딩 단계에서 실패하는지 확인한다.
- 기존 duplicate token/id 정책이 바뀌지 않았는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
### OAR01-1 중간 검증
```bash
$ go test -count=1 ./packages/go/config
(output)
```
### OAR01-2 중간 검증
```bash
$ go test -count=1 ./apps/edge/internal/node
(output)
```
### 최종 검증
```bash
$ go test -count=1 ./packages/go/config ./apps/edge/internal/node
(output)
```
---
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

View file

@ -0,0 +1,211 @@
<!-- task=m-oto-agent-registry-implementation/01_config_store plan=0 tag=OAR01 -->
# OTO Agent Registry - Config and Store
## 이 파일을 읽는 구현 에이전트에게
`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증을 실행하고 실제 변경 내용과 stdout/stderr를 채운 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, 또는 범위 충돌 없이는 진행할 수 없을 때만 review stub의 `사용자 리뷰 요청` 섹션에 근거를 적고 중단한다. 재실행으로 해소 가능한 증거 공백은 사용자 리뷰 요청이 아니다.
## 배경
현재 Edge의 등록 토큰 모델은 `nodes[]` 기반 일반 노드만 표현한다. OTO agent를 같은 등록 경로로 받으려면 설정과 `NodeStore`에 agent kind가 먼저 보존되어야 한다. 이 계획은 후속 registry/transport 작업이 의존할 내부 모델 기반만 추가한다.
## 사용자 리뷰 요청 흐름
구현 중 차단은 active `CODE_REVIEW-*-G??.md``사용자 리뷰 요청` 섹션에 기록한다. 이 섹션은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`에서 복사된 양식이며, `USER_REVIEW.md` 작성과 검증은 code-review가 담당한다.
## Roadmap Targets
- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
- Task ids:
- `agent-kind-model`: Node/Agent 등록 record가 `generic-node``oto-agent`를 구분한다.
- 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`
- `packages/go/config/config.go`
- `packages/go/config/config_test.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/node/store_test.go`
- `configs/edge.yaml`
### 테스트 환경 규칙
`test_env=local`이다. `agent-test/local/rules.md`를 읽었고, 변경 경로 기준으로 `edge-smoke`, `platform-common-smoke`, `testing-smoke` 프로필을 적용한다. 적용 명령은 `go test -count=1 ./packages/go/config ./apps/edge/internal/node`와 최종 `go test -count=1 ./apps/edge/... ./packages/go/config`다. local 규칙은 이번 작업 중 생성된 ignored 로컬 규칙이며 `<확인 필요>` 값은 없다.
### 테스트 커버리지 공백
- `agent_kind` YAML 로딩: 신규 테스트 필요.
- 빈 `agent_kind``generic-node` 기본값: 신규 테스트 필요.
- 허용되지 않는 `agent_kind` 거부: 신규 테스트 필요.
- `NodeStore`가 kind를 보존하고 기존 token/id 중복 정책을 유지: 신규 테스트 필요.
### 심볼 참조
이 계획은 기존 심볼 rename/remove를 하지 않는다. 관련 참조는 `NodeDefinition`, `NodeRecord`, `LoadFromConfig`, `FindByToken`, `FindByID`, `BuildConfigPayload`이며 call site는 `packages/go/config/config.go`, `apps/edge/internal/node/store.go`, `apps/edge/internal/node/mapper.go`, `apps/edge/internal/bootstrap/runtime.go`, `apps/edge/internal/service/service.go`, 관련 테스트다.
### 분할 판단
분할 정책을 먼저 평가했다. 공유 task group은 `m-oto-agent-registry-implementation`이다. 하위 작업은 `01_config_store`(기반 모델), `02+01_registry_transport`(연결 등록과 중복 정책), `03+01,02_service_snapshots`(service snapshot 노출)이다. 이 작업은 선행 의존성이 없는 첫 단계다.
### 범위 결정 근거
이 단계는 `packages/go/config``apps/edge/internal/node/store`의 내부 모델만 수정한다. transport 연결 처리, service snapshot, CLI bootstrap command, Control Plane proto, Client UI, DB persistence, OTO message payload는 후속 작업 범위다.
### 빌드 등급
`local-G06`: 설정/스토어 API 변경이 있지만 범위가 작고 단위 테스트로 결정적으로 검증 가능하다.
## 구현 체크리스트
- [ ] `packages/go/config/config.go`에 agent kind 상수와 `NodeDefinition.AgentKind`를 추가하고 `LoadEdge` 정규화/검증을 구현한다.
- [ ] `apps/edge/internal/node/store.go``NodeRecord``LoadFromConfig`에 agent kind 보존 및 기본값 처리를 추가한다.
- [ ] `packages/go/config/config_test.go``apps/edge/internal/node/store_test.go`에 kind 로딩, 기본값, invalid kind, 중복 정책 회귀 테스트를 추가한다.
- [ ] 중간 및 최종 검증 명령을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [OAR01-1] Config agent kind
#### 문제
`packages/go/config/config.go:43``NodeDefinition`은 OTO agent와 일반 노드를 구분할 필드가 없다. `configs/edge.yaml:88``nodes[]` 예시도 기존 노드만 표현한다.
#### 해결 방법
`NodeDefinition``agent_kind`를 추가하고 빈 값은 `generic-node`로 정규화한다. 허용값은 `generic-node`, `oto-agent`로 제한한다.
Before:
```go
// packages/go/config/config.go:43
type NodeDefinition struct {
Alias string `mapstructure:"alias" yaml:"alias"`
Role string `mapstructure:"role" yaml:"role"`
Token string `mapstructure:"token" yaml:"token"`
Adapters NodeAdapters `mapstructure:"adapters" yaml:"adapters"`
}
```
After:
```go
const (
AgentKindGenericNode = "generic-node"
AgentKindOTOAgent = "oto-agent"
)
type NodeDefinition struct {
Alias string `mapstructure:"alias" yaml:"alias"`
Role string `mapstructure:"role" yaml:"role"`
Token string `mapstructure:"token" yaml:"token"`
AgentKind string `mapstructure:"agent_kind" yaml:"agent_kind"`
Adapters NodeAdapters `mapstructure:"adapters" yaml:"adapters"`
}
```
#### 수정 파일 및 체크리스트
- [ ] `packages/go/config/config.go`: 상수, 필드, 정규화/검증 helper 추가.
- [ ] `packages/go/config/config_test.go`: `agent_kind: oto-agent`, 빈 기본값, invalid kind 테스트 추가.
- [ ] `configs/edge.yaml`: 주석 또는 예시를 최소 변경으로 보강한다. 예시가 혼란을 만들면 생략하고 테스트 fixture만 사용한다.
#### 테스트 작성
작성한다. `TestLoadEdge_NodeAgentKind`, `TestLoadEdge_NodeAgentKindDefault`, `TestLoadEdge_NodeAgentKindInvalid`를 추가한다.
#### 중간 검증
```bash
go test -count=1 ./packages/go/config
```
예상 결과: config package 테스트 PASS.
### [OAR01-2] NodeStore record kind
#### 문제
`apps/edge/internal/node/store.go:11``NodeRecord`는 등록 record kind를 보존하지 않는다. 후속 transport 단계에서 token으로 찾은 record가 OTO agent인지 알 수 없다.
#### 해결 방법
`NodeRecord.AgentKind`를 추가하고 `LoadFromConfig`에서 정규화된 `NodeDefinition.AgentKind`를 복사한다. 기존 alias/id/token 생성 규칙은 유지한다.
Before:
```go
// apps/edge/internal/node/store.go:11
type NodeRecord struct {
ID string
Alias string
Role string
Token string
Adapters config.NodeAdapters
Connected bool
}
```
After:
```go
type NodeRecord struct {
ID string
Alias string
Role string
Token string
AgentKind string
Adapters config.NodeAdapters
Connected bool
}
```
#### 수정 파일 및 체크리스트
- [ ] `apps/edge/internal/node/store.go`: `NodeRecord.AgentKind` 추가, 기본값 fallback 방어 추가.
- [ ] `apps/edge/internal/node/store_test.go`: kind 보존 및 기존 duplicate token/id 회귀 확인.
#### 테스트 작성
작성한다. `TestLoadFromConfigAgentKind`와 기존 duplicate 테스트 보강을 추가한다.
#### 중간 검증
```bash
go test -count=1 ./apps/edge/internal/node
```
예상 결과: node package 테스트 PASS.
## 의존 관계 및 구현 순서
1. `OAR01-1`을 먼저 구현한다.
2. `OAR01-2`는 config 정규화 결과에 의존한다.
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `packages/go/config/config.go` | OAR01-1 |
| `packages/go/config/config_test.go` | OAR01-1 |
| `configs/edge.yaml` | OAR01-1 |
| `apps/edge/internal/node/store.go` | OAR01-2 |
| `apps/edge/internal/node/store_test.go` | OAR01-2 |
## 최종 검증
```bash
go test -count=1 ./packages/go/config ./apps/edge/internal/node
```
예상 결과: 두 package 테스트 PASS. Go test cache output은 허용하지 않으므로 `-count=1`을 유지한다.
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -0,0 +1,126 @@
<!-- task=m-oto-agent-registry-implementation/02+01_registry_transport plan=0 tag=OAR02 -->
# Code Review Reference - OAR02
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-06-03
task=m-oto-agent-registry-implementation/02+01_registry_transport, plan=0, tag=OAR02
## Roadmap Targets
- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/oto-agent-registry-implementation.md`
- Task ids:
- `connected-entry`: 연결된 OTO agent가 Edge 내부 registry entry로 노출된다.
- `duplicate-policy`: 동일 OTO identity/token 중복 연결 정책과 거부 사유가 구분된다.
- Completion mode: check-on-pass
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
1. 판정을 append한다.
2. `CODE_REVIEW-local-G07.md``code_review_local_G07_N.log`, `PLAN-local-G07.md``plan_local_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다. WARN/FAIL이면 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 수정은 런타임 책임이다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [OAR02-1] Registry entry kind and lifecycle | [ ] |
| [OAR02-2] Transport registration kind and duplicate reason | [ ] |
## 구현 체크리스트
- [ ] 시작 전 `01_config_store``complete.log`로 predecessor 완료를 확인한다.
- [ ] `apps/edge/internal/node/registry.go`에 entry kind/lifecycle 필드를 추가하고 기존 registry 동작을 유지한다.
- [ ] `apps/edge/internal/node/mapper.go`가 OTO agent record에서도 안전한 config payload를 만들도록 필요한 기본값만 보강한다.
- [ ] `apps/edge/internal/transport/server.go`에서 token으로 찾은 record의 kind를 registry entry에 전달하고 OTO 중복 거부 사유를 구분한다.
- [ ] registry, mapper, transport tests를 추가/보강하고 중간 및 최종 검증 명령을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_local_G07_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_local_G07_M.log`로 아카이브한다.
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md``agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-oto-agent-registry-implementation/02+01_registry_transport/`를 archive로 이동한다.
- [ ] PASS split 작업이면 이동 후 빈 active parent를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- 구현 전 `01_config_store` 완료 근거가 기록됐는지 확인한다.
- OTO entry가 registry list/get에서 kind/lifecycle을 잃지 않는지 확인한다.
- OTO duplicate reason이 generic duplicate reason을 깨지 않는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
### OAR02-1 중간 검증
```bash
$ go test -count=1 ./apps/edge/internal/node
(output)
```
### OAR02-2 중간 검증
```bash
$ go test -count=1 ./apps/edge/internal/transport
(output)
```
### 최종 검증
```bash
$ go test -count=1 ./apps/edge/internal/node ./apps/edge/internal/transport
(output)
```
---
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

View file

@ -0,0 +1,160 @@
<!-- task=m-oto-agent-registry-implementation/02+01_registry_transport plan=0 tag=OAR02 -->
# OTO Agent Registry - Registry and Transport
## 이 파일을 읽는 구현 에이전트에게
`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증을 실행하고 실제 변경 내용과 stdout/stderr를 채운 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, 또는 범위 충돌 없이는 진행할 수 없을 때만 review stub의 `사용자 리뷰 요청` 섹션에 근거를 적고 중단한다. 재실행으로 해소 가능한 증거 공백은 사용자 리뷰 요청이 아니다.
## 배경
`NodeStore`가 kind를 보존한 뒤에는 연결된 entry와 registration ack 경로가 그 kind를 잃지 않아야 한다. 현재 `NodeRegistry`와 transport server는 모든 연결을 node로만 취급한다. 이 계획은 OTO agent 연결을 같은 토큰 경로로 받되, entry kind와 중복 거부 사유를 구분한다.
## 사용자 리뷰 요청 흐름
구현 중 차단은 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:
- `connected-entry`: 연결된 OTO agent가 Edge 내부 registry entry로 노출된다.
- `duplicate-policy`: 동일 OTO identity/token 중복 연결 정책과 거부 사유가 구분된다.
- 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/node/registry.go`
- `apps/edge/internal/node/registry_test.go`
- `apps/edge/internal/node/mapper.go`
- `apps/edge/internal/node/mapper_test.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/transport/server.go`
- `apps/edge/internal/transport/server_test.go`
- `apps/edge/internal/transport/integration_test.go`
### 테스트 환경 규칙
`test_env=local`이다. 적용 프로필은 `edge-smoke`, `platform-common-smoke`, `testing-smoke`다. 계약 명령은 `go test -count=1 ./apps/edge/internal/node ./apps/edge/internal/transport`와 최종 `go test -count=1 ./apps/edge/...`다.
### 테스트 커버리지 공백
- `NodeEntry.AgentKind` 보존: 신규 registry/mapper 테스트 필요.
- OTO token 연결 후 registry entry kind 확인: 신규 transport test 필요.
- 동일 OTO identity/token 중복 연결 거부 사유: 신규 transport test 필요.
- 기존 generic node 중복 거부 문구 회귀: 기존 테스트 보강 필요.
### 심볼 참조
rename/remove 없음. 관련 call site는 `node.NewRegistry`, `NodeRegistry.Register`, `NodeRegistry.List`, `mapper.BuildConfigPayload`, `transport.Server.onNodeConnected`, `transport.Server.HandleRegister`, transport/server/integration tests다.
### 분할 판단
공유 task group은 `m-oto-agent-registry-implementation`이다. 이 작업은 `02+01_registry_transport`이며 predecessor `01_config_store``complete.log`가 필요하다. 현재 작성 시점에는 predecessor가 아직 완료되지 않았으므로 구현 에이전트는 시작 전 `agent-task/m-oto-agent-registry-implementation/01_config_store/complete.log` 또는 archive의 matching `01_* /complete.log`를 확인해야 한다.
### 범위 결정 근거
이 단계는 registry entry와 transport registration 경로만 수정한다. service snapshot 노출은 `03+01,02_service_snapshots`, CLI bootstrap command는 다음 milestone, proto/schema와 Control Plane wire 변경은 범위 밖이다.
### 빌드 등급
`local-G07`: 연결 경로와 중복 정책을 건드리지만 기존 transport 테스트로 재현 가능한 bounded 변경이다.
## 구현 체크리스트
- [ ] 시작 전 `01_config_store``complete.log`로 predecessor 완료를 확인한다.
- [ ] `apps/edge/internal/node/registry.go`에 entry kind/lifecycle 필드를 추가하고 기존 registry 동작을 유지한다.
- [ ] `apps/edge/internal/node/mapper.go`가 OTO agent record에서도 안전한 config payload를 만들도록 필요한 기본값만 보강한다.
- [ ] `apps/edge/internal/transport/server.go`에서 token으로 찾은 record의 kind를 registry entry에 전달하고 OTO 중복 거부 사유를 구분한다.
- [ ] registry, mapper, transport tests를 추가/보강하고 중간 및 최종 검증 명령을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [OAR02-1] Registry entry kind and lifecycle
#### 문제
`apps/edge/internal/node/registry.go:13``NodeEntry``ID`, `Alias`, `Role`만 공개한다. OTO agent가 연결되어도 내부 registry에서 일반 node와 구분되지 않는다.
#### 해결 방법
`NodeEntry.AgentKind``LifecycleState`를 추가한다. empty kind는 `generic-node`, empty lifecycle은 `connected`로 방어한다. `DisplayLabel`은 이번 범위에서 유지한다.
#### 수정 파일 및 체크리스트
- [ ] `apps/edge/internal/node/registry.go`: 필드 및 register-time 기본값 추가.
- [ ] `apps/edge/internal/node/registry_test.go`: OTO entry kind/lifecycle, 기존 list/get 회귀 테스트 추가.
#### 테스트 작성
작성한다. `TestRegistryRegisterPreservesAgentKind`와 lifecycle 기본값 테스트를 추가한다.
#### 중간 검증
```bash
go test -count=1 ./apps/edge/internal/node
```
예상 결과: node package 테스트 PASS.
### [OAR02-2] Transport registration kind and duplicate reason
#### 문제
`apps/edge/internal/transport/server.go:147`의 registration handler는 token record를 찾은 뒤 모든 연결을 node로 등록한다. `server.go:156` 부근의 중복 연결 거부도 OTO agent와 generic node를 구분하지 않는다.
#### 해결 방법
record의 `AgentKind``NodeEntry`로 복사한다. 동일 ID가 이미 연결된 경우 `oto-agent``oto agent already connected`, 그 외는 기존 node duplicate 문구를 유지한다.
#### 수정 파일 및 체크리스트
- [ ] `apps/edge/internal/transport/server.go`: entry 생성과 duplicate reason 분기 추가.
- [ ] `apps/edge/internal/transport/server_test.go`: OTO registration entry kind와 duplicate reason 테스트 추가.
- [ ] `apps/edge/internal/transport/integration_test.go`: 필요 시 end-to-end registration smoke 보강.
#### 테스트 작성
작성한다. OTO token registration, duplicate OTO registration, generic duplicate 회귀 assertion을 추가한다.
#### 중간 검증
```bash
go test -count=1 ./apps/edge/internal/transport
```
예상 결과: transport package 테스트 PASS.
## 의존 관계 및 구현 순서
이 task directory의 `+01``01_config_store` 완료 의존성을 뜻한다. 구현 전 predecessor `complete.log`를 확인한다. 구현 순서는 registry entry 필드 추가 후 transport 연결 경로 보강이다.
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `apps/edge/internal/node/registry.go` | OAR02-1 |
| `apps/edge/internal/node/registry_test.go` | OAR02-1 |
| `apps/edge/internal/node/mapper.go` | OAR02-2 |
| `apps/edge/internal/node/mapper_test.go` | OAR02-2 |
| `apps/edge/internal/transport/server.go` | OAR02-2 |
| `apps/edge/internal/transport/server_test.go` | OAR02-2 |
| `apps/edge/internal/transport/integration_test.go` | OAR02-2 |
## 최종 검증
```bash
go test -count=1 ./apps/edge/internal/node ./apps/edge/internal/transport
```
예상 결과: node/transport package 테스트 PASS. Go test cache output은 허용하지 않는다.
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -0,0 +1,125 @@
<!-- task=m-oto-agent-registry-implementation/03+01,02_service_snapshots plan=0 tag=OAR03 -->
# Code Review Reference - OAR03
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-06-03
task=m-oto-agent-registry-implementation/03+01,02_service_snapshots, plan=0, tag=OAR03
## 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
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
1. 판정을 append한다.
2. `CODE_REVIEW-local-G06.md``code_review_local_G06_N.log`, `PLAN-local-G06.md``plan_local_G06_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다. WARN/FAIL이면 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 수정은 런타임 책임이다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [OAR03-1] Service snapshot kind fields | [ ] |
| [OAR03-2] Whole edge compatibility | [ ] |
## 구현 체크리스트
- [ ] 시작 전 `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의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_local_G06_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_local_G06_M.log`로 아카이브한다.
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md``agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-oto-agent-registry-implementation/03+01,02_service_snapshots/`를 archive로 이동한다.
- [ ] PASS split 작업이면 이동 후 빈 active parent를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- 구현 전 01/02 predecessor 완료 근거가 기록됐는지 확인한다.
- service snapshot이 OTO kind/lifecycle을 전달하는지 확인한다.
- Control Plane proto/UI 변경이 섞이지 않았는지 확인한다.
- 기존 generic node snapshot과 Edge tests가 회귀하지 않았는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
필수 규칙:
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
### OAR03-1 중간 검증
```bash
$ go test -count=1 ./apps/edge/internal/service ./apps/edge/internal/bootstrap
(output)
```
### OAR03-2 중간 검증
```bash
$ go test -count=1 ./apps/edge/...
(output)
```
### 최종 검증
```bash
$ go test -count=1 ./apps/edge/... ./packages/go/config
(output)
```
---
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

View file

@ -0,0 +1,153 @@
<!-- 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.