<!-- task=m-control-plane-separation-migration/03_core_service plan=1 tag=REVIEW_MONOREPO_CORE -->

# Implementation Plan - REVIEW_MONOREPO_CORE

## 이 파일을 읽는 구현 에이전트에게

구현 완료 전 `CODE_REVIEW-local-G06.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 사용자 결정, 사용자 소유 외부 환경/secret, 또는 범위 충돌이 있으면 review stub의 `사용자 리뷰 요청` 섹션에 근거를 남기고 중단한다. 구현 에이전트는 `USER_REVIEW.md`, archive log, `complete.log`를 만들지 않는다.

## 배경

1차 리뷰에서 Core Service scaffold 자체와 handler tests는 동작했지만, `services/core/oto-core` 실행 바이너리가 source tree에 남아 있고 검증 출력이 exact command와 맞지 않아 FAIL 처리되었다. 이번 후속 작업은 산출물 정리와 검증 증거 신뢰도 복구만 다룬다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. code-review가 검증하고 `USER_REVIEW.md` 작성 여부를 결정한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/independent-control-plane/milestones/control-plane-separation-migration.md`
- Task ids:
  - `core-service`: OTO Server backend가 `services/core` 기준으로 생성되고, health/readiness와 local run entrypoint가 준비된다.
- Completion mode: check-on-pass

## 분석 결과

### 근거 로그

- `agent-task/m-control-plane-separation-migration/03_core_service/plan_local_G05_0.log`
- `agent-task/m-control-plane-separation-migration/03_core_service/code_review_local_G05_0.log`

### 실패 원인

- `services/core/oto-core`는 `7f 45 4c 46` magic byte를 가진 ELF 실행 파일이며 계획된 source file이 아니다.
- `git check-ignore -v services/core/oto-core`는 매칭 없이 종료되어 현재 ignore 대상도 아니다.
- 리뷰 재실행에서 `cd services/core && go test ./...`는 통과했지만, 출력은 non-verbose 형태였다. 기존 review stub에는 `=== RUN` 라인이 포함된 verbose 출력이 exact command 출력처럼 기록되어 있었다.

### 범위 결정 근거

- Go service behavior, endpoint contract, handler tests는 이번 후속 범위에서 바꾸지 않는다.
- runner registry, enrollment, job dispatch, root Makefile 위임은 여전히 제외한다.
- `.gitignore`는 `/services/core/oto-core`처럼 확인된 로컬 빌드 산출물에 한정해 수정한다.

### 빌드 등급

- `local-G06`: 명확한 산출물 정리와 deterministic verification evidence 복구 작업이다.

## 구현 체크리스트

- [ ] `services/core/oto-core` 실행 산출물을 제거한다.
- [ ] `.gitignore`에 `/services/core/oto-core`를 추가해 같은 로컬 빌드 산출물이 추적 후보로 다시 나타나지 않게 한다.
- [ ] `services/core`에서 `go test ./...`를 재실행하고 exact command의 실제 stdout/stderr를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_MONOREPO_CORE-1] Remove Untracked Core Binary

문제: `services/core/oto-core` 실행 파일이 source tree에 남아 있고 ignore되지 않아, 계획 범위 밖 binary artifact가 커밋 후보가 될 수 있다.

해결 방법:

- `services/core/oto-core`를 삭제한다.
- `.gitignore`의 일반 섹션에 `/services/core/oto-core` ignore 항목을 추가한다.
- 변경 후 `test ! -e services/core/oto-core`와 `git check-ignore -v services/core/oto-core`로 제거와 ignore 규칙을 확인한다.

수정 파일 및 체크리스트:
- [ ] `.gitignore`
- [ ] `services/core/oto-core` 삭제

중간 검증:
```bash
test ! -e services/core/oto-core
git check-ignore -v services/core/oto-core
```
예상 결과: 첫 명령은 exit 0, 두 번째 명령은 `.gitignore`의 `/services/core/oto-core` 규칙을 출력한다.

### [REVIEW_MONOREPO_CORE-2] Restore Verification Evidence Trust

문제: 기존 review stub에 `go test ./...` 명령 출력으로 verbose test output이 기록되어 exact command evidence와 맞지 않았다.

해결 방법:

- `cd services/core && go test ./...`를 그대로 재실행한다.
- `CODE_REVIEW-local-G06.md`의 `검증 결과`에는 실제 stdout/stderr를 그대로 붙인다.
- verbose 출력이 필요하면 명령도 `go test -v ./...`로 명시해야 하지만, 이번 계획의 계약은 non-verbose `go test ./...`다.

수정 파일 및 체크리스트:
- [ ] `agent-task/m-control-plane-separation-migration/03_core_service/CODE_REVIEW-local-G06.md`

중간 검증:
```bash
cd services/core && go test ./...
```
예상 결과: 모든 Go package test 통과. 출력은 exact command의 실제 stdout/stderr여야 한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `.gitignore` | REVIEW_MONOREPO_CORE-1 |
| `services/core/oto-core` | REVIEW_MONOREPO_CORE-1 |
| `agent-task/m-control-plane-separation-migration/03_core_service/CODE_REVIEW-local-G06.md` | REVIEW_MONOREPO_CORE-2 |

## 최종 검증

```bash
git status --short .gitignore services/core
cd services/core && go test ./...
```

예상 결과: `services/core/oto-core`가 상태 출력에 나타나지 않고, Go package test가 통과한다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
