<!-- task=03+execution_context_boundaries plan=0 tag=REFACTOR -->

# Code Review Reference - REFACTOR

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Do not modify or check the `코드리뷰 전용 체크리스트`; it is owned by the review agent only.
> Follow the ownership table at the bottom of this file for which sections you own.

## 개요

date=2026-05-20
task=03+execution_context_boundaries, plan=0, tag=REFACTOR

## 이 파일을 읽는 리뷰 에이전트에게

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
review 완료 후 반드시 아래 순서로 아카이브하세요.

1. `CODE_REVIEW-cloud-G08.md` → `code_review_cloud_G08_N.log` (N = 기존 code_review_*.log 수)
2. `PLAN-cloud-G08.md` → `plan_cloud_G08_M.log` (M = 기존 plan_*.log 수)
3. PASS인 경우 `complete.log` 작성 후 `agent-task/archive/YYYY/MM/03+execution_context_boundaries/`로 task 디렉터리 이동. WARN/FAIL인 경우 새 routed plan + review 스텁 작성.

어떤 판정에서도 아카이브를 건너뛰지 마세요. PASS/WARN/FAIL 모두 `코드리뷰 결과` append 후 active plan/review 파일을 먼저 아카이브하고, 그 다음 `complete.log` 또는 다음 plan/review 파일을 작성해야 합니다.
PASS에서는 `agent-ops/skills/common/code-review/templates/complete-log-template.md`의 섹션 순서와 필수 항목을 기준으로 `complete.log`를 작성하세요. 작성 후 현재 날짜의 `YYYY/MM` 기준으로 task 디렉터리를 `agent-task/archive/YYYY/MM/03+execution_context_boundaries/`로 이동하고, 최종 archive 경로의 `code_review_*.log`에서 `코드리뷰 전용 체크리스트`를 갱신한 다음 보고하세요.
WARN/FAIL에서는 다음 상태 파일 작성 후 현재 task 경로의 archived `code_review_*.log`에서 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 체크한 다음 보고하세요.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [REFACTOR-1] TagSystem context parameter | [x] |
| [REFACTOR-2] Command base context injection | [x] |
| [REFACTOR-3] Pipeline carries ExecutionContext | [x] |

## 구현 체크리스트

- [x] `TagSystem` static API에 optional `ExecutionContext` 인자를 추가하고 기본 호환을 유지한다.
- [x] `Command` base에 context 주입 지점을 추가하고 pipeline dispatch에서 설정한다.
- [x] `Pipeline`과 `PipelineExecutor`가 context를 보유하도록 하되 기존 호출 API를 깨지 않는다.
- [x] context 관련 기존 테스트와 runtime/application 테스트를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G08_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G08_M.log`로 아카이브한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 `agent-task/03+execution_context_boundaries/`를 `agent-task/archive/YYYY/MM/03+execution_context_boundaries/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [x] WARN/FAIL이면 다음 active `PLAN-cloud-G08.md`와 `CODE_REVIEW-cloud-G08.md`를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

- **`PipelineExecutor`에 `runtimeContext` getter 추가 (public)**: plan은 `PipelineExe`와 `PipelineExeHandle` 각각에 private `_runtimeContext`를 두는 것을 암시했으나, `PipelineExeHandle`은 다른 파일에 있어 library-private 접근이 불가능하다. `PipelineExecutor` abstract class에 public `runtimeContext` getter를 추가해 모든 하위 클래스가 상속받도록 설계했다.
- **`PipelineAsync.executeAsync`에도 `command.context` 설정**: plan에 명시되지 않았으나 `PipelineAsync`의 async 실행 경로에서도 command에 context를 주입해야 일관성이 유지된다.

## 주요 설계 결정

- **`_defaultContext` static getter**: `Application.instance.context`를 직접 인라인하지 않고 getter로 추출해, 호환 fallback 지점을 단일화했다.
- **`PipelineValidateResult.context` 필드**: `pipelineInitialize`가 결정한 runtimeContext를 `Pipeline` 생성자까지 전달하기 위해 `PipelineValidateResult`에 context를 보유하도록 했다.
- **`pipelineInitialize`에서 `exe.context` 설정 후 `exe.initialize` 호출**: initialize 내부에서 `this.context`를 사용해 nested `validateTasks`에 context를 전달할 수 있도록 초기화 순서를 `set context → initialize`로 정했다.
- **static Command wrapper는 변경 없음**: `Command.replaceAllTagsMap` 등 static 래퍼는 기존 API를 유지한다. instance 메서드만 `TagSystem`을 직접 호출해 `runtimeContext`를 전달한다.

## 리뷰어를 위한 체크포인트

- 기존 `Application.instance` compatibility accessor가 유지되는지 확인한다.
- Pipeline nested task가 같은 `ExecutionContext`를 전달받는지 확인한다.
- `TagSystem` fallback이 기존 테스트를 깨지 않으면서 명시 context를 지원하는지 확인한다.

## 검증 결과

### REFACTOR-1 중간 검증
```bash
$ dart test test/oto_context_test.dart
00:01 +2: All tests passed!
```

### REFACTOR-2 중간 검증
```bash
$ dart test test/oto_command_runtime_test.dart
00:01 +3: All tests passed!
```

### REFACTOR-3 중간 검증
```bash
$ dart test test/oto_application_test.dart test/oto_core_test.dart
00:01 +12: All tests passed!
```

### 최종 검증
```bash
$ dart analyze
Analyzing oto...
No issues found!

$ dart test test/oto_context_test.dart test/oto_command_runtime_test.dart test/oto_application_test.dart test/oto_core_test.dart
00:07 +17: All tests passed!

$ dart run bin/main.dart exe -f assets/yaml/sample/01_basic.yaml
(Build Data 출력 생략)
빌드 시작 - env: dev, version: 1.0.0
[Return] isRelease : false
[Return] retryCount : 0
[Return] buildTag : v1.0.0-dev
빌드 태그: v1.0.0-dev
Build Successfully Complete
```

## 코드리뷰 결과

### 종합 판정

FAIL

### 차원별 평가

| 차원 | 평가 | 근거 |
|------|------|------|
| Correctness | Fail | flow-control 실행 경로의 태그 읽기/쓰기 일부가 전달받은 `ExecutionContext` 대신 `Application.instance.context` fallback을 사용한다. |
| Completeness | Fail | `[REFACTOR-3] Pipeline carries ExecutionContext`가 조건/반복 executor 전체에 완결되지 않았다. |
| Test Coverage | Fail | 명시 `ExecutionContext`와 기본 singleton context가 다른 상황에서 if/while/wait-until/contain/foreach/switch 경로를 검증하는 테스트가 없다. |
| API Contract | Fail | `Pipeline.pipelineInitialize(..., context:)` 계약상 하위 pipeline/flow-control도 같은 context를 사용해야 하나 일부 경로가 이를 지키지 않는다. |
| Code Quality | Pass | 변경 자체는 기존 구조를 유지하며 큰 구조적 문제는 없다. |
| Plan Deviation | Pass | plan의 주된 변경 방향과 파일 범위는 대체로 유지했다. |
| Verification Trust | Pass | `dart analyze`, 지정 테스트, `01_basic` smoke를 재실행했고 모두 통과했다. 다만 해당 검증은 발견된 context 누락을 커버하지 않는다. |

### 발견된 문제

- Required: `PipelineCondition.checkCondition()`이 `Command.replaceSingleTagValue()`/`Command.replaceTagValue()` static wrapper를 호출해 `PipelineExecutor.runtimeContext`를 전달하지 않는다. 이 베이스를 쓰는 `if`, `while`, `wait-until`, `switch` 조건식은 `Pipeline.pipelineInitialize(list, context: explicitContext)`로 만든 pipeline에서도 `Application.instance.context`를 읽게 된다. `lib/oto/pipeline/pipeline_condition.dart:67`, `lib/oto/pipeline/pipeline_condition.dart:72`에서 `TagSystem`에 `context: runtimeContext`를 전달하거나 `PipelineExecutor` instance helper를 통해 같은 context를 사용하도록 고쳐야 한다.
- Required: `foreach`와 `contain` executor도 실행 중 태그 평가/쓰기 태그 저장에 static wrapper를 사용한다. `foreach`는 iterator를 default context에서 읽고 loop 변수도 default context에 쓴다. `contain`은 target/list 태그를 default context에서 읽는다. 명시 context 또는 동시 실행 context에서는 loop body와 조건 분기가 잘못된 property를 보게 된다. `lib/oto/pipeline/pipeline_foreach.dart:55`, `lib/oto/pipeline/pipeline_foreach.dart:65`, `lib/oto/pipeline/pipeline_foreach.dart:79`, `lib/oto/pipeline/pipeline_foreach.dart:81`, `lib/oto/pipeline/pipeline_contain.dart:45`, `lib/oto/pipeline/pipeline_contain.dart:51`을 `runtimeContext` 기반 호출로 바꿔야 한다.
- Required: `DataSwitchValue.validate()`가 `PipelineExecutor.validateTasks(tasks)`를 context 없이 호출한다. `PipelineSwitch.initialize()`가 context를 받더라도 `DataSwitch.validate()` 단계에서 case task 검증은 singleton command map을 보므로, 명시 context의 `dataCommandMap`만 가진 switch pipeline이 검증 실패할 수 있다. `lib/oto/data/pipeline_data.dart:269`의 validation 흐름을 switch executor 쪽 context-aware validation으로 옮기거나 context를 전달할 수 있는 구조로 조정해야 한다.

### 검증 재실행

```bash
$ dart analyze
Analyzing oto...
No issues found!

$ dart test test/oto_context_test.dart test/oto_command_runtime_test.dart test/oto_application_test.dart test/oto_core_test.dart
00:01 +17: All tests passed!

$ dart run bin/main.dart exe -f assets/yaml/sample/01_basic.yaml
Build Successfully Complete
```

### 다음 단계

FAIL: 아래 Required 항목을 해결하는 후속 plan/review를 작성한다.

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave the review-agent-only checklist unchanged.
