<!-- task=m-agent-task-runtime-target-selector/11+10_unknown_isolation plan=13 tag=REVIEW_REFACTOR -->

# Code Review Reference - REVIEW_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.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## 개요

date=2026-07-27
task=m-agent-task-runtime-target-selector/11+10_unknown_isolation, plan=13, tag=REVIEW_REFACTOR

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md)
- Task ids:
  - `throughput-policy`: target별 정적 cap 없이 ready task dispatch와 batch quota snapshot 재사용
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-agent-task-runtime-target-selector/11+10_unknown_isolation/plan_local_G07_12.log`
- Prior review: `agent-task/m-agent-task-runtime-target-selector/11+10_unknown_isolation/code_review_cloud_G07_12.log`
- Verdict: `FAIL`
- Required 1: locator의 첫 durable write가 stable handoff ID보다 앞서서 atomic handoff identity 경계를 만족하지 않는다.
- Required 2: save-fault와 restart regression이 legacy helper/direct `invoke()`에 의존하고 restart에서 provider seam 2회를 기대하므로 production restart exactly-once와 sibling 불변을 검증하지 않는다.
- Suggested: 없음
- Nit: 없음
- Affected files: `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`, `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`
- Verification evidence: focused 3개와 selected dispatcher 20개는 PASS, 전체 256개는 scope 밖 `ReviewControlTest.test_final_channel_contract_is_top_level_and_singular` 1개만 FAIL, `py_compile` 및 `git diff --check`는 PASS했다.
- Ownership/dependency: 기존 split subtask `11+10_unknown_isolation`과 testing domain 소유이며 신규 predecessor, 사용자 결정, 외부 권한은 없다.
- Roadmap carryover: `throughput-policy`, SDD S06/S09/S11의 persisted continuation, dispatch integration, same-batch quota snapshot 불변성을 유지한다.

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

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.

1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` → `code_review_cloud_G07_13.log`, `PLAN-local-G08.md` → `plan_local_G08_13.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-agent-task-runtime-target-selector/11+10_unknown_isolation/`로 이동한다. WARN/FAIL이면 code-review skill이 요구하는 다음 filesystem state를 완전히 작성한다.
4. PASS이고 task group이 `m-agent-task-runtime-target-selector`이므로 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| REVIEW_REFACTOR-1 first-record handoff identity와 commit guard | [x] |
| REVIEW_REFACTOR-2 production scheduler reopen exactly-once regression | [x] |

## 구현 체크리스트

- [x] retry handoff ID를 locator의 첫 durable write 전에 record에 포함하고, matching atomic commit이 false 또는 save fault이면 provider seam에 도달하지 않도록 production ordering을 고친다.
- [x] actual scheduler/`run_worker()`를 거치는 deterministic locator publication, commit save-fault, reopen/restart 회귀로 first-record identity, provider duplicate 0회, normal sibling quota/decision/history 불변을 검증한다.
- [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_G07_13.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_local_G08_13.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-agent-task-runtime-target-selector/11+10_unknown_isolation/`를 `agent-task/archive/YYYY/MM/m-agent-task-runtime-target-selector/11+10_unknown_isolation/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-agent-task-runtime-target-selector`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-agent-task-runtime-target-selector/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [x] WARN/FAIL이면 code-review skill의 판정에 맞는 다음 filesystem state를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

- `dispatch.py`의 REVIEW_REFACTOR-1 변경은 계획의 Before/After 스니펫을 그대로 적용했다 (`retry_handoff_id`를 첫 `write_json` 전에 resolve, `commit_retry_handoff_locator()`가 false를 반환하면 `ExecutionDecisionError`를 raise).
- `test_dispatch.py`는 계획이 명시한 두 test 이름(`test_retry_handoff_production_save_fault_preserves_pending`, `test_retry_restart_does_not_duplicate_provider_or_mutate_sibling`)에 더해, REVIEW_REFACTOR-1의 "focused production test"용으로 `test_retry_handoff_first_locator_record_and_commit_guard`를 추가했다. 계획의 중간 검증 커맨드가 이 세 번째 이름을 이미 명시하고 있어 계획 의도와 일치하는 추가이며 범위 이탈이 아니다.
- `test_retry_handoff_production_save_fault_preserves_pending`에서 "pending 상태 보존"의 비교 기준을 `run_worker()` 호출 이전 snapshot이 아니라 `commit_retry_handoff_locator()` 호출 직전 snapshot으로 잡았다. `run_worker()` 내부의 `persisted_execution_decision()`이 invoke() 도달 전에 failover decision을 정상적으로 commit하므로(`execution_decisions.worker` 등 무관 필드 변경), 전체 state 직렬화 비교를 "run_worker 시작 전"과 맞추면 이 정상 decision commit까지 rollback 대상으로 오판한다. 대신 `commit_retry_handoff_locator`를 스파이로 감싸 그 호출 시작 시점의 state를 스냅샷하고, 호출 뒤와 deep-equal 비교하는 방식으로 correctness 기준을 정확히 "이 commit 시도가 실제로 변경한 필드만" 롤백됐는지로 좁혔다.
- `test_retry_restart_does_not_duplicate_provider_or_mutate_sibling`에서 retry 대상 lane="local"/grade=8 task의 failover 후보 선택 결과는 `run_worker()`가 `evaluated_at`을 고정하지 않고 내부에서 `persisted_execution_decision()`을 호출하기 때문에 실제 실행 시각에 따라 `pi/iop/laguna-s:2.1`이 아닌 `agy/Gemini 3.6 Flash (Medium)` 등 다른 후보가 선택될 수 있음을 확인했다. 검증 대상은 어떤 adapter/target이 선택되는지가 아니라 retry_handoff_id 재사용 여부이므로 assertion을 adapter-agnostic하게 작성했다.

## 주요 설계 결정

- "provider duplicate 0회"는 "재시작 뒤 provider subprocess가 전혀 호출되지 않는다"가 아니라 "같은 `retry_handoff_id`에 대해 `commit_retry_handoff_locator()`가 두 번 호출되지 않는다"로 해석했다. `run_worker()`의 사전 소비 pre-check(`:4719-4748`)와 REVIEW_REFACTOR-1의 else 분기(retry context가 이미 None이면 `store.update_task(active_locator=...)`만 호출) 모두 재시작 뒤 정상 resume 시도가 handoff commit 경로를 다시 타지 않도록 보장하지만, resume 자체는 정당한 새 attempt이므로 provider seam에 다시 도달하는 것은 정상 동작이다. 이 해석에 따라 `test_retry_restart_does_not_duplicate_provider_or_mutate_sibling`은 `store2.commit_retry_handoff_locator`를 `wraps=`로 감싼 spy로 재진입 0회를 직접 assert하고, subprocess 도달 횟수 자체는 "1회(최초) + 1회(정상 resume) = 2회"를 기대값으로 명시했다.
- save-fault 주입은 `store.save`를 전역 카운트가 아니라 `inspect.stack()`으로 호출 스택에 `commit_retry_handoff_locator` 프레임이 있는지 확인하는 방식으로 정확히 표적했다. `next_execution_identity()`(attempt counter)와 `persisted_execution_decision()`(decision commit)도 각각 `store.save()`를 호출하므로 단순 call-count 기반 fault 주입은 잘못된 지점에서 fault를 일으킬 위험이 있었다.
- REVIEW_REFACTOR-1의 first-record guard 테스트(`test_retry_handoff_first_locator_record_and_commit_guard`)는 `dispatch.write_json`을 wrap해 호출 payload를 기록하되, `StateStore.save()`도 내부적으로 `write_json(state.json, ...)`을 호출하므로 `Path(path).name == "locator.json"`으로 필터링해 locator 파일에 대한 durable write 횟수만 assert했다.

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

- `invoke()`의 최초 `write_json()` 전에 retry context의 stable handoff ID가 record에 포함되고, false/mismatch/save fault에서 subprocess seam이 닫히는지 확인한다.
- `commit_retry_handoff_locator()`의 one-save state transition과 failure rollback이 active locator, pending/context를 정확히 보존하는지 확인한다.
- save-fault와 restart 테스트가 legacy helper/direct duplicate `invoke()`가 아니라 `run_worker()` 또는 scheduler의 production reconciliation을 통과하는지 확인한다.
- restart scenario가 first provider launch 뒤 추가 provider launch 0회, StateStore reopen 뒤 retry state 정확성, independent normal sibling quota/decision/history deep equality를 실제로 assert하는지 확인한다.
- SDD S06/S09/S11 evidence와 focused/selected/full-suite 출력이 실제 구현과 일치하는지 확인한다.

## 검증 결과

### Focused first-record and production restart regressions

Command:

```bash
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ThroughputQuotaBatchTest.test_retry_handoff_first_locator_record_and_commit_guard ThroughputQuotaBatchTest.test_retry_handoff_production_save_fault_preserves_pending ThroughputQuotaBatchTest.test_retry_restart_does_not_duplicate_provider_or_mutate_sibling -v
```

_구현 에이전트가 원문 출력을 기록한다._

```
test_retry_handoff_first_locator_record_and_commit_guard (__main__.ThroughputQuotaBatchTest.test_retry_handoff_first_locator_record_and_commit_guard)
Verify the first durable locator write already embeds the stable ... ok
test_retry_handoff_production_save_fault_preserves_pending (__main__.ThroughputQuotaBatchTest.test_retry_handoff_production_save_fault_preserves_pending)
Verify production commit save-fault preserves the pending handoff exactly. ... ------------------------------------------
작업시작: 01_savefault
------------------------------------------
task=route/01_savefault
model=agy/Gemini 3.6 Flash (Medium)
plan=/tmp/tmphw9pnnq_/agent-task/route/01_savefault/PLAN-local-G08.md
work_log=/tmp/tmphw9pnnq_/agent-task/route/WORK_LOG.md
ok
test_retry_restart_does_not_duplicate_provider_or_mutate_sibling (__main__.ThroughputQuotaBatchTest.test_retry_restart_does_not_duplicate_provider_or_mutate_sibling)
Verify production restart does not re-commit an already-consumed handoff. ... ------------------------------------------
작업시작: 01_restart
------------------------------------------
task=route/01_restart
model=agy/Gemini 3.6 Flash (Medium)
plan=/tmp/tmp8h8ohfj4/agent-task/route/01_restart/PLAN-local-G08.md
work_log=/tmp/tmp8h8ohfj4/agent-task/route/WORK_LOG.md
[01_restart][worker][a00] locator=/tmp/tmp8h8ohfj4/.git/agent-task-dispatcher/runs/20260727T053502Z__route__01_restart__p0__worker__a00/locator.json
------------------------------------------
작업시작: 01_restart
------------------------------------------
task=route/01_restart
model=agy/Gemini 3.6 Flash (Medium)
plan=/tmp/tmp8h8ohfj4/agent-task/route/01_restart/PLAN-local-G08.md
work_log=/tmp/tmp8h8ohfj4/agent-task/route/WORK_LOG.md
[01_restart][worker][a01] locator=/tmp/tmp8h8ohfj4/.git/agent-task-dispatcher/runs/20260727T053502Z__route__01_restart__p0__worker__a01/locator.json
ok

----------------------------------------------------------------------
Ran 3 tests in 0.041s

OK
```

### Selected dispatcher regressions

Command:

```bash
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py DynamicFailoverBudgetTest DispatcherCanonicalFailoverIntegrationTest BlockerDrainTest -v
```

_구현 에이전트가 원문 출력을 기록한다._

```
----------------------------------------------------------------------
Ran 20 tests in 0.209s

OK
```

### Full dispatcher suite

Command:

```bash
python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_*.py'
```

_구현 에이전트가 원문 출력을 기록하고, 별도 후보 1개 외 새 실패 여부를 명시한다._

```
FAIL: test_final_channel_contract_is_top_level_and_singular (test_dispatch.ReviewControlTest.test_final_channel_contract_is_top_level_and_singular)

----------------------------------------------------------------------
Ran 257 tests in 13.763s

FAILED (failures=1)
```
exit code: 1

별도 후보 1개 실패: `ReviewControlTest.test_final_channel_contract_is_top_level_and_singular` — 기존 스킬 문서의 `final` 키워드 포함 여부를 검사하는 기존 실패로, 이번 handoff 변경(`dispatch.py`, `test_dispatch.py`)과 무관하다. 이번 변경으로 인한 새 실패는 없다. (테스트 총 개수는 이전 라운드 256개에서, 기존 2개 제거 + 신규 3개 추가로 257개가 됐다.)

### Compile check

Command:

```bash
python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py
```

_구현 에이전트가 exit code와 출력을 기록한다._

```
(no output)
```
exit code: 0

### Symbol coverage

Command:

```bash
rg -n --sort path 'commit_retry_handoff_locator|retry_quota_refresh_context|retry_handoff_id|persisted_execution_decision|asyncio.create_subprocess_exec' agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py
```

_구현 에이전트가 definition/call/test 범위를 기록한다._

- `commit_retry_handoff_locator`: 정의(`dispatch.py:611`), `invoke()` 내 gated 호출(`:3169`), `run_worker()` pre-check 호출(`:4741`), test에서 spy/side_effect로 다수 사용.
- `retry_quota_refresh_context`: StateStore 기본값 초기화(`:509`, `:535`), consume/commit 내부 조회(`:578`, `:631`), `mark_retry_quota_refresh`(`:736`), decision 보존(`:1713`), `invoke()`에서 읽어 record에 임베드(`:3154-3158`), `run_worker()`에서 resume_locator 도출(`:4716`), test 전역에서 다수 assert.
- `retry_handoff_id`: `invoke()`에서 resolve 후 record/commit에 사용(`:3154-3169`), `run_worker()` pre-check에서 locator 파일로부터 읽음(`:4739`), test에서 locator record 검증에 다수 사용.
- `persisted_execution_decision`: 정의(`:1719`), `run_worker()`(`:4754`), `run_review()`류(`:4989`), test 전역에서 다수 호출(신규 테스트 3개 포함).
- `asyncio.create_subprocess_exec`: `invoke()`에서 handoff commit 이후 호출(`:3226`), test에서 deny guard로 patch(신규 테스트 3개 포함).
- 범위가 계획과 일치: 두 Python 파일 내 definition/call/test 모두 포함되고 다른 파일에 대한 참조는 없다.

### Diff check

Command:

```bash
git diff --check
```

_구현 에이전트가 exit code와 출력을 기록한다._

```
(no output)
```
exit code: 0

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## 섹션 소유권

| Section | Owner | Note |
|---------|-------|------|
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS |
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
| 구현 항목별 완료 여부 (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| 구현 체크리스트 (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan |
| 검증 결과 (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `계획 대비 변경 사항` entry |
| 코드리뷰 결과 | Review agent appends | Not included in stub |

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Pass
  - completeness: Fail
  - test coverage: Fail
  - API contract: Pass
  - code quality: Pass
  - implementation deviation: Fail
  - verification trust: Fail
  - spec conformance: Fail
- 발견된 문제:
  - Required — `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py:9845-9995`: 재시작 회귀가 scheduler의 live-locator gate(`dispatch.py:5558-5582`)를 거치지 않고 `run_worker()`를 두 번 직접 호출하며 `:9970-9974`에서 provider seam 2회를 정상으로 허용한다. 이 경로는 `active_stage`와 실제 live process evidence를 만들지 않아, 계획·직전 FAIL이 요구한 “첫 provider launch 뒤 restart 추가 launch 0회”를 증명하지 못한다. StateStore close/reopen 뒤 실제 scheduler가 live locator를 외부 실행으로 분류해 새 worker/provider spawn을 만들지 않음을 검증하고, normal sibling quota/decision/history deep equality를 유지하도록 회귀를 교체해야 한다.
- 다음 단계: WARN/FAIL follow-up — code-review skill의 격리 재평가 결과로 새 PLAN/CODE_REVIEW pair를 작성한다.
