<!-- task=10+07_scheduler_process_runtime_rollout plan=2 tag=REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT -->

# Plan - REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT

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

이 계획은 `code_review_cloud_G08_1.log`의 FAIL 판정에서 나온 Required 항목만 다룬다.
구현의 마지막 단계는 `CODE_REVIEW-cloud-G08.md`의 구현 에이전트 소유 섹션을 모두 채우는 것이다.
아래 `구현 체크리스트` 순서대로 구현하고 중간/최종 검증을 실행한 뒤, 실제 구현 내용과 stdout/stderr를 `CODE_REVIEW-cloud-G08.md`에 기록한다.
리뷰 파일의 아카이브 지시와 `코드리뷰 전용 체크리스트`는 코드리뷰 에이전트 전용이므로 실행하거나 수정하지 않는다.

## 배경

이전 follow-up 구현은 `SchedulerManager` process boundary 일부와 fake runtime 테스트를 추가했지만, `CommandScheduler`의 `-r` 성공 경로에 남은 직접 `exit(0)` 때문에 고정 검색 검증이 계속 실패한다.
또한 테스트는 `CommandScheduler -r`의 exit boundary를 검증하지 않고, `enableScheduler invokes injected exitHandler` 테스트도 실제 `enableScheduler()`를 호출하지 않아 회귀를 잡지 못한다.

## 리뷰 발견 사항

- `lib/cli/commands/command_scheduler.dart:39`의 direct `exit(0)`를 optional exit handler로 치환해야 한다.
- `test/oto_scheduler_runtime_test.dart:187`의 exit handler 테스트를 실제 routing/exit boundary 검증으로 보강해야 한다.

## 구현 체크리스트

- [ ] `CommandScheduler`가 optional exit handler를 주입받고 `-r` 성공 경로에서 직접 `exit(0)`를 호출하지 않게 한다.
- [ ] `test/oto_scheduler_runtime_test.dart`가 `CommandScheduler -r` 라우팅과 injected exit handler를 실제로 검증하게 한다.
- [ ] 고정 검증 명령을 실행하고 직접 호출 검색 결과가 `handler.exit()`만 남는지 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT-1] CommandScheduler direct exit 제거

#### 문제

`CommandScheduler`의 `-r` 성공 경로가 여전히 `exit(0)`를 직접 호출한다.
이 때문에 process/exit boundary 제거 계약과 최종 `rg` 검증이 실패한다.

#### 해결 방법

`CommandScheduler`에 optional `void Function(int)? exitHandler` constructor parameter를 추가한다.
기본값은 기존 운영 동작을 유지하도록 `exit`를 사용한다.
`-r` 성공 경로에서는 직접 `exit(0)` 대신 주입된 `_exitHandler(0)`를 호출한다.
argument routing semantics는 변경하지 않는다.

#### 수정 파일 및 체크리스트

- [ ] `lib/cli/commands/command_scheduler.dart`: `_exitHandler` field와 optional constructor parameter 추가.
- [ ] `lib/cli/commands/command_scheduler.dart`: `-r` branch의 direct `exit(0)` 제거.

#### 테스트 작성

`REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT-2`에서 함께 작성한다.

#### 중간 검증

```bash
rg --sort path -n "ProcessExecutor\\.(start|run)|Process\\.run|Process\\.start|Process\\.killPid|exit\\(" lib/cli/commands/scheduler lib/cli/commands/command_scheduler.dart
```

기대 결과: `lib/cli/commands/scheduler/scheduler_manager.dart`의 `handler.exit()` 외 직접 process/exit 호출 없음.

### [REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT-2] CommandScheduler -r exit boundary 테스트 보강

#### 문제

현재 `command_scheduler accepts injected manager for routing` 테스트는 `-l`, `-t`만 검증한다.
문제가 남아 있던 `-r` 경로와 exit handler 주입은 테스트하지 않는다.
또한 `enableScheduler invokes injected exitHandler` 테스트는 `manager.exitHandler(0)`를 직접 호출하므로 실제 public 동작을 검증하지 못한다.

#### 해결 방법

fake manager에 `regist` 호출 기록을 추가한다.
`CommandScheduler(scheduler: fakeManager, exitHandler: fakeExit)`로 `execute(['-r', 'dummy.yaml'])`를 호출하고, fake manager의 `regist` 인자와 fake exit code가 기록되는지 검증한다.
테스트가 실제 process exit를 호출하지 않아야 한다.
기존의 직접 `manager.exitHandler(0)` 테스트는 실제 회귀를 잡는 테스트로 교체하거나 제거한다.

#### 수정 파일 및 체크리스트

- [ ] `test/oto_scheduler_runtime_test.dart`: fake manager에 `regist` 호출 기록 추가.
- [ ] `test/oto_scheduler_runtime_test.dart`: `CommandScheduler -r`가 injected manager와 injected exit handler를 사용하는지 검증.
- [ ] `test/oto_scheduler_runtime_test.dart`: 실제 동작을 검증하지 않는 direct `manager.exitHandler(0)` 테스트 제거 또는 교체.

#### 테스트 작성

작성한다.

#### 중간 검증

```bash
dart test test/oto_scheduler_runtime_test.dart
```

기대 결과: scheduler runtime 테스트 통과.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/cli/commands/command_scheduler.dart` | REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT-1 |
| `test/oto_scheduler_runtime_test.dart` | REVIEW_REVIEW_SYSTEM_RUNTIME_SCHEDULER_ROLLOUT-2 |
| `agent-task/10+07_scheduler_process_runtime_rollout/CODE_REVIEW-cloud-G08.md` | 구현 에이전트 소유 섹션 작성 |

## 최종 검증

```bash
test -f agent-task/archive/2026/05/07_system_runtime_foundation/complete.log || test -f agent-task/07_system_runtime_foundation/complete.log
dart format --output=none --set-exit-if-changed lib/cli/commands/scheduler/scheduler_manager.dart lib/cli/commands/scheduler/scheduler_linux.dart lib/cli/commands/scheduler/scheduler_osx.dart lib/cli/commands/scheduler/scheduler_windows.dart lib/cli/commands/command_scheduler.dart test/oto_scheduler_runtime_test.dart
dart analyze
dart test test/oto_scheduler_runtime_test.dart
rg --sort path -n "ProcessExecutor\\.(start|run)|Process\\.run|Process\\.start|Process\\.killPid|exit\\(" lib/cli/commands/scheduler lib/cli/commands/command_scheduler.dart
```

기대 결과: 선행 complete marker 존재, 포맷/analyze/test 성공, `rg`는 `handler.exit()` 외 직접 process/exit 호출을 보고하지 않음.

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