oto/agent-roadmap/archive/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.md
toki 7e51ef913d refactor: runner-proto-socket-transport-hardening 마일스톤을 archive로 이동
- runner-proto-socket-transport-hardening 마일스톤을 agent-roadmap/archive로 이동
- 관련 SDD 문서를 archive로 이동
- PHASE.md 업데이트
2026-06-21 05:56:48 +09:00

10 KiB

SDD: Runner proto-socket transport hardening

위치

  • Milestone: agent-roadmap/phase/control-plane-product-surface/milestones/runner-proto-socket-transport-hardening.md
  • Phase: agent-roadmap/phase/control-plane-product-surface/PHASE.md

상태

[승인됨]

SDD 잠금

  • 상태: 해제
  • 사용자 리뷰: 없음
  • 잠금 항목:
    • 없음

문제 / 비목표

  • 문제: OTO runner transport가 proto-socket push/session과 HTTP claim/polling compatibility 경로를 함께 갖고 있어, 기본 production runner loop, 상태 전이, cancel/status/self-update 방향, smoke evidence의 source of truth가 흐려질 수 있다.
  • 비목표:
    • HTTP public operator API 전체 제거
    • production-grade 인증/권한/감사 로그
    • durable artifact storage와 장기 scheduler policy
    • iop Edge 직접 연결 경로 복원

Source of Truth

영역 기준 메모
Roadmap agent-roadmap/phase/control-plane-product-surface/milestones/runner-proto-socket-transport-hardening.md Milestone 기능 Task와 완료 반영 기준
Code services/core/internal/runnersocket/server.go server-runner proto-socket register, heartbeat, RunRequest dispatch, report, cancel push 기준
Code apps/runner/lib/oto/agent/registration_client.dart Dart runner socket session, heartbeat, pushed RunRequest 수신 기준
Code apps/runner/lib/oto/agent/agent_runner.dart 기본 agent loop가 socket push session을 우선 소비하는 기준
Code services/core/internal/httpserver/routes.go operator-facing HTTP API와 compatibility runner HTTP endpoint 경계
Code proto/oto/runner.proto wire message 이름과 필드 계약
Domain Rule agent-ops/rules/project/domain/agent/rules.md 기본 runner 경로는 proto-socket이고 HTTP polling은 compatibility fallback이라는 정책 기준
External Provider 없음 이 Milestone은 외부 provider write를 추가하지 않는다.
User Decision 없음 기본 방향과 범위는 Milestone 및 domain rule로 결정되어 있다.

State Machine

상태 진입 조건 다음 상태 근거
runner.accepted RegisterRunnerRequest가 enrollment token, runner id, protocol version, capability 검증을 통과한다. runner.online, runner.disconnected, runner.heartbeat_timeout runnerregistry.Register, runnersocket.RegisterRunnerRequest handler
runner.online socket session에서 register 직후 또는 heartbeat가 성공한다. runner.disconnected, runner.heartbeat_timeout runnerregistry.Heartbeat, socket disconnect listener, timeout loop
runner.disconnected 현재 socket client가 닫히고 server가 해당 client를 현재 runner client로 보고 있다. runner.accepted duplicate/reconnect는 re-register를 통해 새 accepted record를 만든다.
job.queued operator HTTP API가 run_request를 포함한 job을 생성한다. job.running, job.failed, job.canceled cicdstate.Store, socket dispatcher
job.running socket dispatcher가 queued job을 claim하고 execution을 생성한 뒤 RunRequest를 push한다. job.succeeded, job.failed, job.canceled runnersocket.DispatchQueuedJobs, handleExecutionReport, CancelJobExecution
execution.running job dispatch가 runner id를 execution owner로 고정하고 RunRequest를 runner에 보낸다. execution.succeeded, execution.failed, execution.canceled cicdstate.Store, runner report/cancel handlers
execution.canceled operator HTTP cancel action이 store를 canceled로 전환하고 연결된 runner socket에 best-effort cancel message를 보낸다. terminal terminal report는 store transition guard와 report handler에서 모순 없이 거부/기록되어야 한다.

Interface Contract

  • 계약 원문: 없음. Wire source는 proto/oto/runner.proto이며 SDD에는 원문을 복제하지 않는다.
  • 입력:
    • RegisterRunnerRequest: runner identity, enrollment token, protocol version, capability, command catalog.
    • HeartbeatRequest: runner liveness와 health status.
    • RunRequest: server가 socket으로 runner에 push하는 job/execution 실행 입력. pipeline_yaml 또는 pipeline_yaml_path 중 정확히 하나만 유효하다.
    • ExecutionReportRequest: runner가 socket으로 보고하는 terminal execution 결과.
    • LogAppendRequest / ArtifactReportRequest: runner가 socket으로 보고하는 execution log/artifact metadata.
    • CancelRunRequest: operator HTTP cancel action 이후 server가 연결된 runner socket에 best-effort로 전달하는 cancel signal.
    • RunnerStatusRequest / SelfUpdateRequest: proto에는 남아 있지만 이 Milestone에서는 status source와 self-update 실행 범위를 명시적으로 고정한 뒤 구현 또는 범위 제외한다.
  • 출력:
    • register/heartbeat/report/log/artifact response는 accepted/success 여부와 structured error를 반환한다.
    • operator-facing HTTP status/self-update response는 UI/operator가 읽는 상태와 deferral 결과를 반환한다.
  • 금지:
    • 기본 agent loop를 HTTP jobs/claim polling 확장 대상으로 삼지 않는다.
    • HTTP runner job claim/report/log/artifact 경로를 기본 smoke나 production runner transport로 설명하지 않는다.
    • terminal execution/job 상태를 cancel 이후 runner report로 되돌리지 않는다.
    • generated protobuf 파일을 수동 수정하지 않는다.

Acceptance Scenarios

ID Milestone Task Given When Then
S01 socket-contract Milestone과 agent domain rule이 proto-socket 기본 경로를 선언한다. SDD와 domain rule을 확인한다. SDD Acceptance Scenario와 domain rule 모두 HTTP polling을 기본 runner path로 설명하지 않는다.
S02 session-lifecycle 같은 runner id가 재연결하거나 heartbeat/disconnect가 발생한다. socket server가 register, heartbeat, duplicate client close, disconnect/timeout을 처리한다. server-assigned runner id reconciliation과 disconnect 상태 전이가 Go/Dart unit 또는 smoke에서 검증된다.
S03 dispatch-state queued job과 invalid RunRequest 후보가 있다. socket dispatcher가 idle runner에 RunRequest를 push한다. queued -> running -> terminal, invalid input -> failed, active execution gate가 socket dispatch 테스트로 검증된다.
S04 runner-actions operator가 cancel/status/self-update HTTP action을 호출한다. server가 store, registry, runner socket message 방향을 적용한다. cancel은 runner 실행과 store state 사이에 모순된 terminal report를 만들지 않고, status/self-update 범위가 구현 또는 명시적 범위 제외로 고정된다.
S05 compat-boundary HTTP runner claim/report/log/artifact compatibility 코드가 남아 있다. 기본 agent loop, smoke, 테스트 이름/그룹을 정리한다. OtoServerSocketRegistrationClient가 기본이고 HTTP polling 테스트는 compatibility 이름/그룹으로만 남는다.
S06 socket-smoke local/remote smoke 기준이 runner transport 완료 근거로 쓰인다. agent smoke 문서와 테스트가 socket 연결 중심 evidence를 요구한다. cd services/core && go test ./..., cd apps/runner && dart analyze, agent socket smoke test가 통과한다.

Evidence Map

Scenario Required Evidence agent-task 연결 Spec Completion 기대
S01 agent-roadmap/sdd/.../SDD.mdagent-ops/rules/project/domain/agent/rules.md가 proto-socket 기본 경로와 HTTP compatibility 경계를 같은 방향으로 설명한다. roadmap-only update socket-contract: SDD와 domain rule에서 HTTP polling이 기본 경로가 아님을 확인
S02 Go/Dart unit 또는 smoke가 server-assigned runner id, duplicate connection close, disconnect/timeout, heartbeat failure를 검증한다. agent-task/m-runner-proto-socket-transport-hardening/01_socket_lifecycle session-lifecycle: lifecycle 상태 전이와 재연결 기준 검증
S03 socket dispatch 테스트가 queued -> running -> terminal, invalid input -> failed, active execution gate를 검증한다. agent-task/m-runner-proto-socket-transport-hardening/02+01_dispatch_state dispatch-state: socket dispatch 상태 전이 검증
S04 cancel/status/self-update 테스트가 operator HTTP action과 socket message/store state 방향을 검증하거나 self-update 실행 범위 제외를 명시한다. agent-task/m-runner-proto-socket-transport-hardening/03+01,02_runner_actions runner-actions: cancel terminal report 모순 방지와 action 범위 고정
S05 search/test evidence가 기본 agent loop와 기본 smoke에서 HTTP polling claim/report를 제거하고 compatibility 그룹으로만 남겼음을 보여준다. agent-task/m-runner-proto-socket-transport-hardening/04+01_compat_boundary compat-boundary: 기본 runner transport와 compatibility test naming 분리
S06 agent socket smoke와 local test rule/profile evidence가 socket-centered smoke 기준을 요구하고 통과한다. agent-task/m-runner-proto-socket-transport-hardening/05+02,03,04_socket_smoke socket-smoke: Go test, Dart analyze, agent socket smoke 통과

Cross-repo Dependencies

  • 없음

Drift Check

  • Milestone 기능 Task와 Acceptance Scenario가 일치한다.
  • Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
  • agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
  • 사용자 리뷰가 필요한 항목은 USER_REVIEW.md에만 남겼다.

사용자 리뷰 이력

  • 없음

작업 컨텍스트

  • 표준선: server/operator-facing HTTP API는 유지하고, runner-facing 내부 실행 transport는 proto-socket push/session으로 둔다.
  • 표준선: HTTP runner claim/report/log/artifact 경로는 삭제 전 compatibility fallback으로만 남기며, 기본 agent loop와 기본 smoke evidence에서는 제외한다.
  • 표준선: cancel은 operator HTTP action에서 store를 terminal canceled로 바꾸고 연결된 socket runner에 best-effort signal을 보낸다. runner-side cooperative stop이 부족하면 그 구현을 runner-actions plan에서 다루고, self-update의 실제 binary replacement는 범위 제외 또는 후속 Milestone으로 고정한다.
  • 후속 SDD: 없음