- Add runner-proto-socket-transport-hardening milestone and SDD docs - Add runnersocket package for Go service - Update agent config, runner, and job client (Dart) - Update Bootstrap scripts (PowerShell, shell) - Update Go service HTTP server handlers and routes - Add CICD state store updates - Update agent-ops domain rules and phase roadmap
10 KiB
Plan - API
이 파일을 읽는 구현 에이전트에게
CODE_REVIEW-cloud-G07.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것까지가 구현입니다. 검증을 실행하고 실제 stdout/stderr를 붙인 뒤 active 파일을 그대로 두고 review ready로 보고하세요. 선택된 SDD 결정 또는 Milestone 구현 잠금 > 결정 필요 항목이 막으면 review stub의 사용자 리뷰 요청 섹션을 채우고 멈추며, 직접 사용자에게 질문하거나 USER_REVIEW.md, complete.log, archive를 만들지 않습니다. 환경/secret/서비스 문제나 증거 공백은 일반 follow-up 대상으로 기록합니다.
배경
현 Milestone은 runner 기본 transport를 proto-socket push/session 기준으로 고정한다. DispatchQueuedJobs는 queued execution을 claim한 뒤 socket runner에게 RunRequest를 보내고, runner는 terminal report를 socket으로 돌려준다. 이 작업은 queued job dispatch와 execution state transition을 socket-first 경로에서 검증해 HTTP claim/polling 잔존 동작과 섞이지 않도록 한다.
사용자 리뷰 요청 흐름
사용자 리뷰 요청은 선택된 SDD 결정 또는 선택된 Milestone lock 결정이 실구현을 차단할 때만 active CODE_REVIEW-cloud-G07.md의 사용자 리뷰 요청 섹션에 기록한다. 구현 중 직접 사용자 프롬프트, 채팅 선택지, request_user_input, USER_REVIEW.md 생성은 금지이며, code-review가 검증과 파일 생성을 소유한다.
Roadmap Targets
- Milestone:
agent-roadmap/phase/control-plane-product-surface/milestones/runner-proto-socket-transport-hardening.md - Task ids:
dispatch-state: queued job dispatch, active execution gate, invalid RunRequest failure, terminal state transition을 socket transport 기준으로 검증한다.
- Completion mode: check-on-pass
- Split dependency:
01_socket_lifecyclePASS complete evidence가 있어야 구현을 시작한다. 미충족이면 코드 변경 없이 dependency pending으로 보고한다.
Spec Targets
- SDD:
agent-roadmap/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.md - Acceptance scenarios:
S03: task=dispatch-state; evidence=Socket RunRequest dispatch와 terminal report가 queued/running/completed/failed/cancelled 상태 전이를 검증한다.
- Completion mode: spec-check-on-pass
분석 결과
읽은 파일
agent-test/local/rules.mdagent-test/local/agent-smoke.mdagent-test/local/framework-smoke.mdagent-ops/rules/project/domain/agent/rules.mdagent-ops/rules/project/domain/framework/rules.mdagent-roadmap/phase/control-plane-product-surface/milestones/runner-proto-socket-transport-hardening.mdagent-roadmap/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.mdservices/core/internal/runnersocket/server.goservices/core/internal/httpserver/server_test.goservices/core/internal/cicdstate/store.goservices/core/internal/cicdstate/store_test.goapps/runner/lib/oto/agent/registration_client.dartapps/runner/lib/oto/agent/agent_runner.dartapps/runner/test/oto_server_connection_smoke_test.dartproto/oto/runner.protoMakefile
테스트 환경 규칙
test_env=local을 적용했다. agent-test/local/rules.md는 agent 변경 시 cd apps/runner && dart analyze, 관련 dart test, cd services/core && go test ./...를 요구한다. 이 plan은 proto schema 변경 없이 socket dispatch/state test와 필요한 server/runner 보강만 다룬다.
테스트 커버리지 공백
- socket queued dispatch가
claimNextQueuedJob을 통해 하나의 queued execution만 running으로 전환하는지 직접 검증이 부족하다. - invalid
RunRequest전송 실패가 execution을 failed로 마감하는지 socket server 단위 테스트가 없다. - socket terminal report가 running 상태에서 completed/failed/cancelled 계열로만 전이하는지 HTTP report tests와 분리된 증거가 부족하다.
심볼 참조
runnersocket.Server.DispatchQueuedJobs, claimNextQueuedJob, ReportExecutionResult, proto.RunRequest, ReportRunResultRequest, OtoServerPushJobSession을 중심으로 확인했다. removed/renamed symbol 없음.
분할 판단
이 작업은 01_socket_lifecycle의 session 안정화 결과에 의존한다. 후속 03+01,02_runner_actions와 05+02,03,04_socket_smoke가 이 작업의 PASS evidence에 의존한다.
범위 결정 근거
이 plan은 queued execution dispatch와 state transition만 다룬다. cancel/status/self-update operator action 방향은 03+01,02_runner_actions, HTTP compatibility 경계는 04+01_compat_boundary, smoke 문서/명령 정리는 05+02,03,04_socket_smoke에서 다룬다.
빌드 등급
cloud-G07: state transition은 Go server store와 socket transport, Dart runner session이 함께 얽히며 회귀 영향이 커서 full local Go test와 targeted Dart smoke가 필요하다.
구현 체크리스트
- 선행
01_socket_lifecyclePASS complete evidence를 확인한다. - [API-1] socket queued dispatch와 invalid RunRequest failure 테스트/보강을 구현한다. 검증:
cd services/core && go test -count=1 ./... - [API-2] socket terminal report와 active execution gate 테스트/보강을 구현한다. 검증:
cd services/core && go test -count=1 ./... - runner socket smoke 관련 회귀를 확인한다. 검증:
cd apps/runner && dart test test/oto_server_connection_smoke_test.dart - CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
[API-1] socket queued dispatch와 invalid RunRequest failure
문제: server.go의 DispatchQueuedJobs는 connected runner 목록을 순회하고 server.go의 claimNextQueuedJob으로 queued execution을 running으로 바꾼다. 다만 socket dispatch 단위에서 "한 queued job만 claim", "runner 전송 실패 시 failed"가 고정되어 있지 않다.
해결 방법:
// before: services/core/internal/runnersocket/server.go:75
func (s *Server) DispatchQueuedJobs(ctx context.Context) {
for _, runnerID := range s.connectedRunnerIDs() {
...
execution, job, ok, err := s.claimNextQueuedJob(ctx, runnerID)
...
}
}
services/core/internal/runnersocket/server_test.go에 dispatch 전용 tests를 추가한다. fake or loopback proto-socket client로 RunRequest 수신을 확인하고, 전송 오류/invalid request fixture에서는 FailExecution 또는 동일 정책의 failed transition을 검증한다. HTTP claim handler tests와 assertion 이름을 분리해 socket dispatch evidence로 읽히게 한다.
수정 파일 및 체크리스트:
services/core/internal/runnersocket/server_test.go에 queued dispatch test 추가- dispatch가 runner id와 queued execution filter를 지키는지 검증
- send failure 또는 invalid request가 execution을 failed로 마감하는지 검증
- 필요 시
services/core/internal/runnersocket/server.go보강
테스트 작성: 작성한다. 테스트 이름 후보: TestServerDispatchQueuedJobOverSocket, TestServerFailsExecutionWhenRunRequestCannotBeSent.
중간 검증:
cd services/core && go test -count=1 ./...
기대 결과: 모든 Go package 통과.
[API-2] socket terminal report와 active execution gate
문제: server.go의 report handler는 runner terminal report를 받아 ReportExecutionResult로 넘긴다. store.go의 state transition guard가 있으나 socket report path에서 active execution과 runner ownership이 어긋난 경우의 test evidence가 부족하다.
해결 방법:
// before: services/core/internal/runnersocket/server.go:197
s.handlers.Register(func(ctx context.Context, req *pb.ReportRunResultRequest) (*pb.ReportRunResultResponse, error) {
err := s.state.ReportExecutionResult(ctx, req.ExecutionId, cicdstate.ExecutionResult{...})
...
})
socket report handler tests를 추가해 running execution만 terminal report를 받을 수 있는지, completed/failed report가 terminal state와 timestamps/log fields를 보존하는지 확인한다. cancelled 상태와 terminal report가 충돌하는 경우에는 현재 store 정책을 테스트로 고정하거나, SDD의 cancelled evidence가 필요하면 store guard를 보강한다.
수정 파일 및 체크리스트:
- socket report success/completed test 추가
- socket report failure test 추가
- wrong runner 또는 non-running execution report guard test 추가
- cancelled state와 terminal report 충돌 정책을 테스트로 고정
- 필요 시
services/core/internal/cicdstate/store.go보강
테스트 작성: 작성한다. 테스트 이름 후보: TestServerReportsRunResultOverSocket, TestServerRejectsTerminalReportForInactiveExecution.
중간 검증:
cd services/core && go test -count=1 ./...
기대 결과: 모든 Go package 통과.
수정 파일 요약
| 파일 | 항목 |
|---|---|
services/core/internal/runnersocket/server.go |
API-1, API-2 |
services/core/internal/runnersocket/server_test.go |
API-1, API-2 |
services/core/internal/cicdstate/store.go |
API-2 |
services/core/internal/cicdstate/store_test.go |
API-2 |
apps/runner/test/oto_server_connection_smoke_test.dart |
API-1, API-2 |
최종 검증
cd services/core && go test -count=1 ./...
cd apps/runner && dart test test/oto_server_connection_smoke_test.dart
기대 결과: Go tests 통과, socket connection smoke 통과. 모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.