# Milestone: Runner proto-socket transport hardening

## 위치

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

## 목표

OTO Server와 runner 사이의 기본 내부 연결을 proto-socket 장기 세션으로 고정하고, 급하게 붙인 HTTP job claim/polling 잔존 경로를 compatibility 경계로 격리한다.
완료 후 bootstrap으로 연결된 runner는 register, heartbeat, pushed RunRequest, execution/log/artifact report를 socket 기준으로 검증하며, cancel/status/self-update의 방향성과 실패 처리가 문서와 테스트에서 같은 계약을 바라봐야 한다.

## 상태

[완료]

## 구현 잠금

- 상태: 해제
- SDD: 필요
- SDD 문서: `agent-roadmap/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.md`
- SDD 사유: server-runner 장기 연결, lifecycle/state machine, cancel/self-update 방향성, HTTP compatibility 축소는 API/proto/config/env와 field smoke에 영향을 주므로 구현 전에 계약을 고정해야 한다.
- 잠금 해제 조건:
  - [x] SDD 상태가 `[승인됨]`이고 SDD 잠금이 해제되어 있다.
  - [x] SDD `USER_REVIEW.md`가 없거나 승인/해결되었다.
  - [x] Acceptance Scenario가 아래 기능 Task와 연결되어 있다.
  - [x] Evidence Map이 plan의 `Spec Targets`와 완료 시 `Spec Completion`으로 검증 가능하게 연결되어 있다.
- 결정 필요:
  - 없음. 기본 방향은 `proto-socket` push/session을 production runner transport로 두고, HTTP runner job claim/polling은 compatibility 경계로 축소한다.

## 범위

- OTO Server runner socket listener와 Dart runner socket client/session의 register, heartbeat, run dispatch, report, disconnect lifecycle을 정리한다.
- HTTP job claim/report/log/artifact 경로는 public operator API와 runner transport compatibility를 분리해 문서, 명명, 테스트에서 기본 경로로 보이지 않게 한다.
- cancel/status/self-update가 socket push/session과 HTTP operator action 사이에서 어떤 방향으로 흐르는지 고정한다.
- bootstrap/config/env에서 `server.url`과 `server.socket_url`의 책임을 분리하고 기본 포트/공개 URL 계산을 검증한다.

## 기능

### Epic: [socket-transport] Runner socket transport 정리

기본 runner transport를 proto-socket으로 고정하고, HTTP polling 잔재를 compatibility 경계로 격리한다.

- [x] [socket-contract] register, heartbeat, RunRequest push, execution/log/artifact report의 server-runner 방향성과 메시지 계약을 SDD와 domain rule에 고정한다. 검증: SDD Acceptance Scenario와 domain rule이 HTTP polling을 기본 경로로 설명하지 않는다.
- [x] [session-lifecycle] runner id reconciliation, duplicate connection close, disconnect/timeout, reconnect 후보, heartbeat 실패 처리의 socket session lifecycle을 정리한다. 검증: Go/Dart unit 또는 smoke가 server-assigned runner id와 disconnect 상태 전이를 확인한다.
- [x] [dispatch-state] queued job dispatch, invalid RunRequest 실패 처리, active execution gate, terminal state 전이를 socket dispatch 기준으로 정리한다. 검증: socket dispatch 테스트가 queued -> running -> terminal 및 invalid input -> failed를 확인한다.
- [x] [runner-actions] cancel/status/self-update의 operator HTTP action과 runner socket message 방향을 정리하고 구현 또는 명시적 범위 제외로 고정한다. 검증: cancel이 runner 실행과 store state 사이에서 모순된 terminal report를 만들지 않는다.
- [x] [compat-boundary] HTTP runner job claim/report/log/artifact 경로를 compatibility로 격리하고 기본 agent loop와 기본 smoke에서 제거한다. 검증: `OtoServerSocketRegistrationClient`가 기본이고 HTTP polling 테스트는 compatibility 이름/그룹으로만 남는다.
- [x] [socket-smoke] local/remote smoke 기준을 proto-socket 연결 중심으로 갱신한다. 검증: `cd services/core && go test ./...`, `cd apps/runner && dart analyze`, agent socket smoke test가 통과한다.

## 완료 리뷰

- 상태: 통과
- 요청일: 2026-06-21
- 완료 근거:
  - `socket-contract`는 SDD와 agent domain rule의 proto-socket 기본 경로/HTTP compatibility 경계 정리로 완료되어 있다.
  - `agent-task/archive/2026/06/m-runner-proto-socket-transport-hardening/*/complete.log`의 `Roadmap Completion`과 `Spec Completion`이 `session-lifecycle`, `dispatch-state`, `runner-actions`, `compat-boundary`, `socket-smoke` 및 SDD `S02`~`S06`을 PASS로 기록했다.
  - 최종 검증 근거에는 `cd services/core && go test -count=1 ./...`, `cd apps/runner && dart analyze`, runner/agent Dart smoke tests, `git diff --check` PASS가 포함된다.
- 검토 항목: 코드레벨 완료 검토와 로컬 검증 통과로 `[완료]` 전환 및 archive 이동을 수행한다.
- 리뷰 코멘트: 구현 잠금과 SDD 잠금은 해제되어 있고 남은 결정 필요 항목은 없다. Workspace lock 관련 항목은 없다.

## 범위 제외

- iop Edge 직접 연결 경로를 복원하지 않는다.
- production-grade 인증/권한/감사 로그는 `Control Plane 운영 보안·감사 표면` Milestone에서 다룬다.
- durable artifact storage와 장기 job scheduler policy는 이 Milestone에서 완성하지 않는다.
- HTTP public operator API 전체를 제거하지 않는다. 제거/축소 대상은 runner 내부 transport로 쓰이던 HTTP job claim/polling 경로다.

## 작업 컨텍스트

- 관련 경로: `services/core/internal/runnersocket/**`, `services/core/internal/httpserver/**`, `services/core/cmd/oto-core/**`, `apps/runner/lib/oto/agent/**`, `apps/runner/assets/script/**/oto_agent_bootstrap.*`, `proto/oto/runner.proto`, `agent-test/local/agent-smoke.md`
- 표준선(선택): server/operator-facing HTTP API는 유지하고, runner-facing 내부 실행 transport는 proto-socket으로 둔다.
- 표준선(선택): HTTP runner claim/report 코드는 삭제 전 compatibility fallback으로 남기더라도 기본 agent loop, bootstrap, smoke 기준에서는 제외한다.
- 선행 작업: `Runner bootstrap, OTO binary, 노드 연결`, `Control Plane API 데이터 바인딩`, `Control Plane 운영 액션 표면`
- 후속 작업: 운영 보안·감사 표면, durable persistence, 운영 대시보드 고도화
- 확인 완료: SDD에서 cancel/self-update의 즉시 구현 범위와 compatibility endpoint 제거/유지 기준을 검증 가능한 acceptance로 고정했다.
