<!-- task=03+execution_context_boundaries plan=1 tag=REVIEW_REFACTOR -->

# Execution Context Boundary Follow-up

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

이 계획은 `code_review_cloud_G08_0.log`의 FAIL Required 항목만 해결한다.
새 구조를 크게 만들기보다 기존 `ExecutionContext` 전달 설계를 flow-control executor 전체에 완결시키는 것을 목표로 한다.
구현 완료의 마지막 단계는 `CODE_REVIEW-cloud-G08.md`의 구현 에이전트 소유 섹션을 모두 채우는 것이다.

## 배경

1차 구현은 `TagSystem`, `Command`, `Pipeline`, `PipelineExecutor`에 context 전달 지점을 추가했지만, 일부 pipeline flow-control 실행 경로가 여전히 `Command` static wrapper를 통해 `Application.instance.context` fallback을 사용한다.
그 결과 `Pipeline.pipelineInitialize(list, context: explicitContext)`로 명시 context를 전달해도 조건식, foreach loop 변수, contain 평가, switch case validation이 singleton context를 볼 수 있다.

## 리뷰 실패 요약

- `PipelineCondition.checkCondition()`의 tag read가 `runtimeContext`를 쓰지 않는다.
- `PipelineForeach`와 `PipelineContain`의 tag read/write가 `runtimeContext`를 쓰지 않는다.
- `DataSwitchValue.validate()`가 context 없이 nested tasks를 validate한다.
- 위 경로를 명시 context와 singleton context가 다른 상태에서 검증하는 테스트가 없다.

## 구현 체크리스트

- [x] `PipelineCondition`의 조건식 태그 치환이 `runtimeContext`를 사용하도록 수정한다.
- [x] `PipelineForeach`와 `PipelineContain`의 실행 중 태그 읽기/쓰기 호출이 `runtimeContext`를 사용하도록 수정한다.
- [x] `PipelineSwitch` case task validation이 명시 `ExecutionContext`의 command map을 사용하도록 수정한다.
- [x] flow-control이 명시 `ExecutionContext`를 사용하는 회귀 테스트를 추가하거나 기존 테스트에 보강한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REFACTOR-1] PipelineCondition runtime context

#### 문제

`PipelineCondition.checkCondition()`은 `Command.replaceSingleTagValue()`와 `Command.replaceTagValue()` static wrapper를 호출한다.
이 wrapper는 호환 목적으로 `Application.instance.context` fallback을 사용하므로, `PipelineExecutor.context`가 설정되어 있어도 `if`, `while`, `wait-until`, `switch` 조건식이 명시 context를 읽지 못한다.

Before:

```dart
value0 = Command.replaceSingleTagValue(list[0]);
value1 = Command.replaceTagValue(list[1]);
```

#### 해결 방법

`TagSystem`을 직접 호출하거나 `PipelineExecutor`에 작은 instance helper를 추가해 `runtimeContext`를 전달한다.
기존 public static wrapper 시그니처는 호환을 위해 그대로 둔다.

After 예시:

```dart
value0 = TagSystem.replaceSingleTagValue(list[0], context: runtimeContext);
value1 = TagSystem.replaceTagValue(list[1], context: runtimeContext);
```

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

- [x] `lib/oto/pipeline/pipeline_condition.dart`: 조건식 양변 tag read에 `runtimeContext` 전달.
- [x] 필요 시 `lib/oto/pipeline/pipeline_exe.dart`: executor 공통 helper 추가.

#### 테스트 작성

명시 context에는 조건 property를 넣고 `Application.instance.context`에는 다른 값을 넣은 뒤, `PipelineIf` 또는 `PipelineWaitUntil`이 명시 context 기준으로 평가되는지 검증한다.

#### 중간 검증

```bash
dart test test/oto_core_test.dart test/oto_application_test.dart
```

### [REVIEW_REFACTOR-2] Foreach and contain runtime context

#### 문제

`PipelineForeach.execute()`는 iterator read와 loop variable write를 static wrapper로 수행한다.
`PipelineContain.execute()`도 target/list tag read를 static wrapper로 수행한다.
명시 context pipeline에서는 loop body가 default context에 저장된 값 또는 default context에서 읽은 값을 보게 된다.

Before:

```dart
var iterator = Command.replaceTagValue(data.iterator);
await Command.setPropertyValue(elementTag, item);
var value = Command.replaceSingleTagValue(data.target);
```

#### 해결 방법

모든 실행 중 tag read/write에 `runtimeContext`를 전달한다.
반복 body로 만들어진 nested pipeline은 이미 같은 context를 전달받으므로 loop 변수도 같은 context에 기록되어야 한다.

After 예시:

```dart
var iterator = TagSystem.replaceTagValue(data.iterator, context: runtimeContext);
await TagSystem.setPropertyValue(elementTag, item, context: runtimeContext);
var value = TagSystem.replaceSingleTagValue(data.target, context: runtimeContext);
```

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

- [x] `lib/oto/pipeline/pipeline_foreach.dart`: iterator read, setKey/setValue write에 context 전달.
- [x] `lib/oto/pipeline/pipeline_contain.dart`: target/list tag read에 context 전달.

#### 테스트 작성

명시 context의 list/map을 foreach로 순회하고 loop 변수 또는 downstream command가 명시 context property를 보는지 검증한다.
contain은 singleton context와 명시 context의 값이 다른 상태에서 분기 결과가 명시 context 기준인지 검증한다.

#### 중간 검증

```bash
dart test test/oto_core_test.dart test/oto_application_test.dart
```

### [REVIEW_REFACTOR-3] Switch case validation context

#### 문제

`DataSwitchValue.validate()`는 `PipelineExecutor.validateTasks(tasks)`를 context 없이 호출한다.
`PipelineSwitch.initialize()`가 context를 받아도 `DataSwitch.fromJson(...).validate()` 내부에서 case tasks가 singleton context의 command map으로 검증된다.

Before:

```dart
var validateResult = PipelineExecutor.validateTasks(tasks);
```

#### 해결 방법

`DataSwitchValue.validate()`에서 nested pipeline validation을 하지 않거나, context를 받을 수 있는 별도 validation 경로를 만든다.
권장 방향은 pipeline 구조와 context를 알고 있는 `PipelineSwitch.initialize()`에서 각 case의 `tasks`를 `PipelineExecutor.validateTasks(item.tasks, context: context)`로 검증하고, `DataSwitchValue.validate()`는 case 값 자체의 구조 검증만 담당하게 하는 것이다.

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

- [x] `lib/oto/data/pipeline_data.dart`: `DataSwitchValue.validate()`의 context 없는 nested task validation 제거 또는 context-aware 경로로 변경.
- [x] `lib/oto/pipeline/pipeline_switch.dart`: initialize 시 case tasks를 명시 context로 validate.
- [x] 실행 시 재검증이 필요하면 `PipelineExecutor.validateTasks(item.tasks, context: context)`를 유지하되 failure 처리도 명확히 한다.

#### 테스트 작성

`Application.instance.context.dataCommandMap`은 비워두고 별도 `ExecutionContext.dataCommandMap`에 switch case command만 넣은 뒤 `Pipeline.pipelineInitialize(..., context: explicitContext)`가 성공하는지 검증한다.

#### 중간 검증

```bash
dart test test/oto_core_test.dart test/oto_application_test.dart
```

### [REVIEW_REFACTOR-4] Explicit context regression tests

#### 문제

기존 검증은 default singleton context 기반 실행과 smoke test를 확인하지만, 명시 context와 singleton context가 다른 상황을 만들지 않는다.
그래서 이번 누락이 테스트에서 드러나지 않았다.

#### 해결 방법

기존 테스트 파일을 우선 수정한다.
새 파일이 꼭 필요하지 않다면 `test/oto_core_test.dart`에 `ExecutionContext` 명시 전달 기반 pipeline validation/execution 단위 테스트를 추가한다.
필요하면 `test/oto_application_test.dart`에는 user-facing build 성공/실패 계약만 유지한다.

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

- [x] `test/oto_core_test.dart` 또는 관련 기존 테스트: 명시 context와 singleton context가 다른 값을 가진 회귀 테스트 추가.
- [x] 테스트가 실제로 실패를 잡는지 assertion을 구체화한다.

#### 중간 검증

```bash
dart test test/oto_core_test.dart test/oto_application_test.dart
```

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/oto/pipeline/pipeline_condition.dart` | REVIEW_REFACTOR-1 |
| `lib/oto/pipeline/pipeline_foreach.dart` | REVIEW_REFACTOR-2 |
| `lib/oto/pipeline/pipeline_contain.dart` | REVIEW_REFACTOR-2 |
| `lib/oto/data/pipeline_data.dart` | REVIEW_REFACTOR-3 |
| `lib/oto/pipeline/pipeline_switch.dart` | REVIEW_REFACTOR-3 |
| `test/oto_core_test.dart` | REVIEW_REFACTOR-4 |
| `test/oto_application_test.dart` | REVIEW_REFACTOR-4 검증 대상 |

## 최종 검증

```bash
dart analyze
dart test test/oto_context_test.dart test/oto_command_runtime_test.dart test/oto_application_test.dart test/oto_core_test.dart
dart run bin/main.dart exe -f assets/yaml/sample/01_basic.yaml
```

기대 결과: analyze와 지정 테스트가 통과하고, `01_basic` 샘플 실행이 `Build Successfully Complete`를 출력한다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-cloud-G08.md`의 구현 에이전트 소유 섹션을 채운다.
