- runner-proto-socket-transport-hardening 마일스톤을 agent-roadmap/archive로 이동 - 관련 SDD 문서를 archive로 이동 - PHASE.md 업데이트
10 KiB
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/claimpolling 확장 대상으로 삼지 않는다. - HTTP runner job claim/report/log/artifact 경로를 기본 smoke나 production runner transport로 설명하지 않는다.
- terminal execution/job 상태를 cancel 이후 runner report로 되돌리지 않는다.
- generated protobuf 파일을 수동 수정하지 않는다.
- 기본 agent loop를 HTTP
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.md와 agent-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-actionsplan에서 다루고, self-update의 실제 binary replacement는 범위 제외 또는 후속 Milestone으로 고정한다. - 후속 SDD: 없음