<!-- task=m-runner-proto-socket-transport-hardening/04+01_compat_boundary plan=0 tag=API -->

# 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 SDD는 runner 기본 연결을 proto-socket으로 고정하고 HTTP job claim/report/log/artifact 경로를 compatibility fallback으로 축소한다. 현재 runner는 socket registration 실패 시 HTTP session으로 fallback하고, HTTP route/tests는 여전히 기본 runner path처럼 보이는 이름과 smoke 배치를 일부 갖고 있다. 이 작업은 HTTP 경로를 제거하지 않고 경계와 이름, 검증 기준을 정리한다.

## 사용자 리뷰 요청 흐름

사용자 리뷰 요청은 선택된 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:
  - `compat-boundary`: HTTP job claim/polling/report/log/artifact 경로를 compatibility fallback으로 격리하고 기본 runner path 명명에서 제외한다.
- Completion mode: check-on-pass
- Split dependency:
  - `01_socket_lifecycle` PASS complete evidence가 있어야 구현을 시작한다.

## Spec Targets

- SDD: `agent-roadmap/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.md`
- Acceptance scenarios:
  - `S05`: task=`compat-boundary`; evidence=`HTTP job claim/report/log/artifact 경로가 compatibility fallback으로 격리되고 기본 smoke/문서가 socket path를 기준으로 한다.`
- Completion mode: spec-check-on-pass

## 분석 결과

### 읽은 파일

- `agent-test/local/rules.md`
- `agent-test/local/agent-smoke.md`
- `agent-test/local/framework-smoke.md`
- `agent-ops/rules/project/domain/agent/rules.md`
- `agent-ops/rules/project/domain/framework/rules.md`
- `agent-roadmap/phase/control-plane-product-surface/milestones/runner-proto-socket-transport-hardening.md`
- `agent-roadmap/sdd/control-plane-product-surface/runner-proto-socket-transport-hardening/SDD.md`
- `services/core/internal/httpserver/routes.go`
- `services/core/internal/httpserver/job_handlers.go`
- `services/core/internal/httpserver/runner_handlers.go`
- `services/core/internal/httpserver/server_test.go`
- `apps/runner/lib/oto/agent/agent_runner.dart`
- `apps/runner/lib/oto/agent/registration_client.dart`
- `apps/runner/lib/oto/agent/oto_server_job_client.dart`
- `apps/runner/test/oto_agent_registration_test.dart`
- `apps/runner/test/oto_server_connection_smoke_test.dart`
- `Makefile`

### 테스트 환경 규칙

`test_env=local`을 적용했다. 이 작업은 대부분 naming, fallback boundary, tests/docs 정리지만 agent/core 경로를 건드릴 수 있으므로 Go test, Dart targeted tests, analyzer, deterministic `rg --sort path` evidence를 사용한다.

### 테스트 커버리지 공백

- HTTP polling loop가 fallback임을 test names/pass criteria가 일관되게 표현하지 않는다.
- `OtoServerRegistrationClient`와 `OtoServerJobClient.claimNextJob`가 기본 path smoke처럼 보일 수 있다.
- HTTP routes는 유지되어야 하지만 compatibility route로 분류되는 evidence가 부족하다.

### 심볼 참조

`OtoServerPushJobSession`, `OtoServerSocketRegistrationClient`, `OtoServerRegistrationClient`, `OtoServerJobClient.claimNextJob`, `/api/runners/jobs/claim`, `jobs/{id}/report`, `jobs/{id}/logs`, `jobs/{id}/artifacts`를 중심으로 확인했다. removed/renamed symbol 없음.

### 분할 판단

이 작업은 session lifecycle이 먼저 안정화되어야 fallback naming이 의미 있다. dispatch/action 구현과 직접 충돌하지 않도록 HTTP compatibility naming과 test grouping만 좁게 다룬다.

### 범위 결정 근거

HTTP job endpoints를 삭제하지 않는다. 기존 외부/legacy runner compatibility를 깨지 않고, 기본 agent path와 smoke 기준에서 socket-first를 명확히 하는 데 집중한다.

### 빌드 등급

`cloud-G07`: 기능 삭제는 아니지만 route/test naming과 default path 기준이 바뀌면 runner smoke와 운영 문서 신뢰도에 영향이 있다.

## 구현 체크리스트

- [ ] 선행 `01_socket_lifecycle` PASS complete evidence를 확인한다.
- [ ] [API-1] runner default path와 HTTP fallback boundary를 코드/테스트 이름에서 분리한다. 검증: `cd apps/runner && dart test test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart`
- [ ] [API-2] core HTTP job endpoints가 compatibility로 유지되는지 tests/docs evidence를 정리한다. 검증: `cd services/core && go test -count=1 ./...`
- [ ] [API-3] deterministic grep evidence로 기본 smoke/docs가 socket-first인지 확인한다. 검증: 아래 `rg --sort path` 명령
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [API-1] runner default path와 HTTP fallback boundary 분리

문제: [agent_runner.dart](/config/workspace/oto/apps/runner/lib/oto/agent/agent_runner.dart:77)는 socket session을 먼저 시도하고 실패 시 HTTP session으로 fallback한다. 그러나 [agent_runner.dart](/config/workspace/oto/apps/runner/lib/oto/agent/agent_runner.dart:135)의 HTTP polling loop와 tests가 기본 runner 동작처럼 읽힐 수 있다.

해결 방법:

```dart
// before: apps/runner/lib/oto/agent/agent_runner.dart:77
final socketSession = await _tryStartSocketSession(config, registration);
if (socketSession != null) {
  return _runPushLoop(socketSession);
}
return _runPollingLoop(...);
```

fallback behavior는 유지하되, function/test group/log wording을 compatibility fallback으로 정리한다. socket path test를 first/default smoke로 두고 HTTP polling tests는 legacy/compatibility group으로 분리한다.

수정 파일 및 체크리스트:

- [ ] runner test group names에서 socket default와 HTTP compatibility를 구분
- [ ] HTTP fallback log/test wording이 default path로 읽히지 않게 정리
- [ ] socket session 실패 시 fallback behavior는 기존대로 보존
- [ ] 필요 시 `agent-ops/rules/project/domain/agent/rules.md` 문구와 일치하도록 테스트명 보강

테스트 작성: 기존 tests rename/grouping 또는 신규 assertion 작성.

중간 검증:

```bash
cd apps/runner && dart test test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart
```

기대 결과: targeted Dart tests 통과.

### [API-2] core HTTP job endpoints compatibility evidence 정리

문제: [routes.go](/config/workspace/oto/services/core/internal/httpserver/routes.go:107)는 HTTP runner job routes를 계속 노출한다. 이는 legacy compatibility로 필요하지만 Milestone 기본 transport와 혼동되면 안 된다.

해결 방법:

HTTP job claim/report/log/artifact tests는 compatibility/fallback group으로 유지한다. route 제거는 하지 않는다. endpoint docs/comments/test names가 기본 transport처럼 보이면 compatibility wording으로 정리한다.

수정 파일 및 체크리스트:

- [ ] HTTP job claim/report/log/artifact tests가 compatibility fallback evidence로 읽히도록 정리
- [ ] route behavior는 유지
- [ ] socket dispatch tests와 HTTP claim tests가 서로 다른 책임을 갖도록 이름 분리

테스트 작성: 기존 Go tests 이름/grouping 또는 comments 정리.

중간 검증:

```bash
cd services/core && go test -count=1 ./...
```

기대 결과: 모든 Go package 통과.

### [API-3] grep evidence와 smoke/docs 정리

문제: smoke criteria와 docs가 socket-first를 명확히 하지 않으면 후속 작업이 HTTP polling을 기본 evidence로 제출할 수 있다.

해결 방법:

`agent-test/local/agent-smoke.md`, domain rule, tests를 정리한 뒤 deterministic grep으로 socket-first/fallback wording을 확인한다.

수정 파일 및 체크리스트:

- [ ] `agent-test/local/agent-smoke.md`가 socket smoke를 기본으로 요구하는지 확인/수정
- [ ] HTTP 관련 wording이 compatibility fallback으로 제한되는지 확인
- [ ] `rg --sort path` 결과를 CODE_REVIEW 검증 결과에 붙임

중간 검증:

```bash
rg --sort path -n "OtoServerRegistrationClient|claimNextJob|jobs/claim|HTTP polling|compatibility|fallback|socket" apps/runner/lib apps/runner/test services/core/internal/httpserver agent-ops/rules/project/domain/agent/rules.md agent-test/local/agent-smoke.md
```

기대 결과: HTTP client/claim/polling 언급이 compatibility/fallback 맥락으로 분리되어 보인다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/runner/lib/oto/agent/agent_runner.dart` | API-1 |
| `apps/runner/lib/oto/agent/registration_client.dart` | API-1 |
| `apps/runner/lib/oto/agent/oto_server_job_client.dart` | API-1 |
| `apps/runner/test/oto_agent_registration_test.dart` | API-1 |
| `apps/runner/test/oto_server_connection_smoke_test.dart` | API-1, API-3 |
| `services/core/internal/httpserver/routes.go` | API-2 |
| `services/core/internal/httpserver/server_test.go` | API-2 |
| `agent-test/local/agent-smoke.md` | API-3 |
| `agent-ops/rules/project/domain/agent/rules.md` | API-3 |

## 최종 검증

```bash
cd apps/runner && dart test test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart
cd services/core && go test -count=1 ./...
cd apps/runner && dart analyze
rg --sort path -n "OtoServerRegistrationClient|claimNextJob|jobs/claim|HTTP polling|compatibility|fallback|socket" apps/runner/lib apps/runner/test services/core/internal/httpserver agent-ops/rules/project/domain/agent/rules.md agent-test/local/agent-smoke.md
```

기대 결과: tests/analyzer 통과, grep 결과에서 HTTP path는 compatibility/fallback 맥락으로 구분된다. 모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
