<!-- task=08+07_core_process_runtime_rollout plan=0 tag=SYSTEM_RUNTIME_CORE_ROLLOUT -->

# Plan - SYSTEM_RUNTIME_CORE_ROLLOUT

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

**구현의 마지막 단계는 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 모두 채우는 것이다. 이 파일이 채워지기 전에는 작업이 완료된 것이 아니다.**
아래 `구현 체크리스트` 순서대로 구현하고 중간/최종 검증을 실행한 뒤, 실제 구현 내용과 stdout/stderr를 `CODE_REVIEW-cloud-G07.md`에 기록한다.
리뷰 파일의 아카이브 지시와 `코드리뷰 전용 체크리스트`는 코드리뷰 에이전트 전용이므로 실행하거나 수정하지 않는다.

## 배경

`Application.setUTF8()`과 `DataComposerJenkins`는 core 도메인인데 직접 process API를 호출한다.
foundation task의 `SystemRuntime`을 사용해 core의 외부 실행 경계를 fake 가능하게 만든다.

## 의존 관계 및 구현 순서

디렉터리 이름의 `08+07`에 따라 `agent-task/07_system_runtime_foundation/complete.log`가 먼저 있어야 한다.
이 task는 foundation API가 merge된 뒤 시작한다.

## 분석 결과

### 읽은 파일

- `lib/oto/application.dart`
- `lib/oto/core/data_composer.dart`
- `lib/oto/core/system_runtime.dart` (선행 task 예정 파일)
- `test/oto_application_test.dart`
- `test/oto_system_runtime_test.dart` (선행 task 예정 파일)

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

- `Application.setUTF8()` Windows branch: 기존 테스트 없음. fake runtime OS flag로 `chcp 65001` 호출을 검증한다.
- `DataComposerJenkins` Linux/macOS branch: 기존 테스트 없음. fake runtime stdout으로 Jenkins map과 `BuildData`를 합성하는 테스트를 추가한다.
- `DataComposerJenkins` Windows branch: 현재 OS 의존 `Platform.isWindows` 때문에 직접 테스트가 어렵다. `SystemRuntime.isWindows`로 분기 이전 후 fake runtime으로 검증한다.

### 심볼 참조

none. 기존 public method 이름은 유지한다.

### 분할 판단

분할 정책을 먼저 평가했다.
core rollout은 `Application`/`DataComposer` 소유 경계 안에 있고, cli/scheduler rollout은 별도 디렉터리 `09+07`, `10+07`로 분리되어 있다.
이 task는 `07_system_runtime_foundation`에만 의존한다.

### 범위 결정 근거

포함: `Application.setUTF8()`, `_mapComposer`, `DataComposerJenkins` process 호출.
제외: `Printer`, `RegistPath`, `SchedulerManager`; 각각 후속 sibling task에서 처리한다.
제외: `CommandRuntime`; command 도메인 계약은 변경하지 않는다.

### 빌드 등급

`cloud-G07`: core process boundary와 Jenkins env/stdout parsing을 다루는 terminal/process-control 작업이다.

## 구현 체크리스트

- [ ] `Application`과 `DataComposerJenkins`가 `SystemRuntime`을 사용하게 한다.
- [ ] core runtime fake 테스트를 추가한다.
- [ ] 중간 검증과 최종 검증 명령을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [SYSTEM_RUNTIME_CORE_ROLLOUT-1] Application/DataComposer runtime 주입

#### 문제

`lib/oto/application.dart:81`은 `setUTF8()`를 await하지 않고, `lib/oto/application.dart:169`는 `ProcessExecutor.start()`를 직접 호출한다.
`lib/oto/core/data_composer.dart:67`, `72`, `77`, `126`도 직접 process API를 호출해 Jenkins compose를 fake runtime으로 검증하기 어렵다.

#### 해결 방법

`Application`에 `SystemRuntime systemRuntime = const DefaultSystemRuntime()`를 추가한다.
`_mapComposer`는 `DataComposerJenkins(runtime: systemRuntime)`를 생성하게 바꾸고 `build()`는 `await setUTF8()`로 호출한다.
`DataComposerJenkins`는 생성자로 runtime을 받고 `runtime.isWindows/isLinux/isMacOS`, `runtime.runShell`, `runtime.startShell`, `runtime.runExecutable`을 사용한다.

Before (`lib/oto/application.dart:81`):
```dart
setUTF8();
```

After:
```dart
await setUTF8();
```

Before (`lib/oto/core/data_composer.dart:67`):
```dart
var result = await ProcessExecutor.run(StringBuffer(script));
```

After:
```dart
final result = await runtime.runShell(StringBuffer(script));
```

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

- [ ] `lib/oto/application.dart`: `SystemRuntime` 주입 필드, awaited `setUTF8`, composer factory 연결.
- [ ] `lib/oto/core/data_composer.dart`: `DataComposerJenkins` 생성자와 process 호출 runtime 이전.

#### 테스트 작성

작성한다.
`test/oto_application_test.dart` 또는 `test/oto_system_runtime_test.dart`에 `setUTF8 uses injected system runtime on Windows`를 추가한다.
`test/oto_system_runtime_test.dart`에 `DataComposerJenkins composes linux env and BuildData from runtime stdout`를 추가한다.

#### 중간 검증

```bash
dart test test/oto_application_test.dart test/oto_system_runtime_test.dart
```

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

### [SYSTEM_RUNTIME_CORE_ROLLOUT-2] core 직접 process 호출 제거 검증

#### 문제

후속 작업이 다시 직접 호출을 추가해도 현재 검색 검증이 없다.

#### 해결 방법

결정적 검색 검증을 최종 검증에 포함한다.
허용 예외가 생기면 plan deviation에 사유를 기록해야 한다.

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

- [ ] `test/oto_system_runtime_test.dart`: fake runtime fixture 재사용.

#### 테스트 작성

작성한다.
테스트명은 위 항목과 동일하게 runtime call capture를 검증한다.

#### 중간 검증

```bash
rg --sort path -n "ProcessExecutor\\.(start|run)|Process\\.run|Process\\.start" lib/oto/application.dart lib/oto/core/data_composer.dart
```

기대 결과: stdout 없음.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/oto/application.dart` | SYSTEM_RUNTIME_CORE_ROLLOUT-1 |
| `lib/oto/core/data_composer.dart` | SYSTEM_RUNTIME_CORE_ROLLOUT-1 |
| `test/oto_application_test.dart` | SYSTEM_RUNTIME_CORE_ROLLOUT-1 |
| `test/oto_system_runtime_test.dart` | SYSTEM_RUNTIME_CORE_ROLLOUT-1, SYSTEM_RUNTIME_CORE_ROLLOUT-2 |

## 최종 검증

```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/oto/application.dart lib/oto/core/data_composer.dart test/oto_application_test.dart test/oto_system_runtime_test.dart
dart analyze
dart test test/oto_application_test.dart test/oto_system_runtime_test.dart
rg --sort path -n "ProcessExecutor\\.(start|run)|Process\\.run|Process\\.start" lib/oto/application.dart lib/oto/core/data_composer.dart
```

기대 결과: 선행 complete marker 존재, 포맷/analyze/test 성공, `rg` stdout 없음.

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