<!-- task=m-agent-task-runtime-target-selector/05+04_dispatch_route_source plan=1 tag=REFACTOR -->

# Plan - Dispatcher persisted route source 연결

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

선행 `04+03_failover_budget`의 `complete.log`가 확인된 뒤 구현한다. 구현과 검증을 끝낸 뒤 `CODE_REVIEW-cloud-G09.md`의 구현 에이전트 소유 섹션을 실제 내용과 원문 출력으로 채운다. active 파일은 그대로 두고 review 준비 완료만 보고한다. 종결은 code-review skill 전용이다. 차단되면 정확한 원인, 시도한 명령/출력, 재개 조건만 구현 에이전트 소유 evidence에 기록한다. 사용자에게 질문하거나 user-input 도구를 호출하지 않고, control-plane stop file 생성, 다음 상태 분류, archive/log 이동, `complete.log` 또는 roadmap 수정은 하지 않는다.

## 배경

dispatcher의 worker, review, dry-run이 파일명 lane/G에서 정적 route를 다시 계산하지 않고 선행 selector decision을 유일한 실행 기준으로 소비하게 만든다.

## 분석 결과

### 읽은 파일

- `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`
- `agent-test/local/rules.md`

### SDD 기준

- 대상 Acceptance Scenario는 S05와 S09다. persisted route pin과 worker/review initial invocation evidence 중 route source 연결 범위만 소유한다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`가 존재하며 끝까지 읽었다.
- agent-ops Python dispatcher에 매칭되는 `agent-test/local/*.md` profile은 없다. 현재 checkout의 Python test manifest를 fallback 근거로 삼아 fresh-process `unittest`, `py_compile`, `git diff --check`를 사용하며 test-rule 유지보수는 필요하지 않다.
- provider subprocess는 fake runner와 임시 workspace/state/locator로 대체하고 실제 cloud/local 호출은 하지 않는다.
- 계획 시점 전체 Python suite 기준선은 169 tests PASS다.

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

- worker route, review initial invocation, dry-run이 selector decision 대신 정적 `route_agent()`를 소비한다.
- dry-run의 persisted resume preview와 non-persisted initial preview가 분리돼 있지 않다.

### 심볼 참조

- `route_agent()` 정의 `dispatch.py:977`과 `run_worker()`(`dispatch.py:3423`), dry-run(`dispatch.py:4201`), 관련 테스트 참조를 selector bridge로 옮긴 뒤 제거한다.

### 분할 판단

- 원본 `05+04_dispatch_integration`을 route source, runtime quota/failover, context/review recovery의 세 behavior slice로 한 단계 분할했다.
- 이 child는 첫 producer이며 `04+03_failover_budget`만 선행한다.

### 범위 결정 근거

- persisted decision의 생성 정책, quota probe, failover budget은 변경하지 않고 live invocation 소비 경계만 교체한다.
- selfcheck target 재사용과 throughput 정책은 후속 sibling 범위다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`
- finalizer=`finalize-task-policy.sh`, finalizer_mode=`pair`; build/review status=`routed`.
- build closures: `scope_closed=true`(승인 SDD와 이 subtask 경계가 고정됨), `context_closed=true`(명시된 source/test 범위를 한 local 작업에서 유지 가능), `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`.
- review closures: `scope_closed=true`, `context_closed=true`(동일 source/test 및 구현 evidence로 판정 가능), `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`.
- build route_basis=`local-fit`; capability_gap=`none`.
- build loop-risk audit: matched signatures=`temporal_state`, `boundary_contract`, `variant_product`; 이 기록은 lane/G를 바꾸지 않는다.
- build scores(scope_coupling/state_concurrency/blast_irreversibility/evidence_diagnosis/verification_complexity)=`2/2/1/1/2`, final=`local-G08`, filename=`PLAN-local-G08.md`.
- review route_basis=`official-review`; official execution=`codex/gpt-5.6-sol xhigh`; capability_gap=`none`.
- review scores(scope_coupling/state_concurrency/blast_irreversibility/evidence_diagnosis/verification_complexity)=`2/2/1/2/2`, final=`cloud-G09`, filename=`CODE_REVIEW-cloud-G09.md`.

## 구현 체크리스트

- [ ] worker/review initial invocation과 dry-run이 persisted selector decision을 단일 route source로 사용한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

## 구현 항목

### [REFACTOR-1] Live route source 교체

- 문제: `dispatch.py:977`의 `route_agent()`와 worker/dry-run call-site가 파일명 lane/G를 정적 CLI spec으로 다시 해석한다.
- 해결 방법:

```python
# Before: agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py:3423
agent = route_agent(task)
```

```python
# After
decision = state.resolve_execution_decision(task, stage=stage, transition=transition)
agent = agent_spec_from_decision(decision)
```

  selector decision 생성과 저장을 원자적으로 연결하고 이미 저장된 stage decision은 반드시 resume으로 검증한다. `route_agent()`와 위에 열거한 source/test call-site를 제거한다. 공식 review는 selector의 review 고정 결과를 쓰고 worker decision을 재사용하지 않는다. dry-run은 persisted decision이 있으면 read-only resume preview, 없으면 non-persisted initial preview만 만들며 state/history/admission 기록을 쓰지 않는다.
- 수정 파일 및 체크리스트:
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`: live worker/review/dry-run route 소비자와 static helper 제거.
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: 제거된 helper 참조 갱신과 initial/review/dry-run assertions.
- 테스트 작성: `test_dispatch.py`의 `SelectorDispatcherIntegrationTest`에서 정적 matrix와 selector 결과가 다른 temp task, fake runner, reopened state를 사용해 worker/review initial과 dry-run 무상태를 검증한다.
- 중간 검증: `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py SelectorDispatcherIntegrationTest -v` — initial/review/dry-run case가 PASS해야 한다.

## 의존 관계 및 구현 순서

1. `04+03_failover_budget`의 archived `complete.log`가 PASS여야 한다.
2. 이 task가 PASS하면 `06+05_runtime_quota_failover`가 persisted route source를 소비한다.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py` | REFACTOR-1 |
| `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py` | REFACTOR-1 |

## 최종 검증

- `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py SelectorDispatcherIntegrationTest -v` — initial/review/dry-run case PASS.
- `python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_*.py'` — fresh process 전체 suite PASS.
- `python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py agent-ops/skills/project/orchestrate-agent-task-loop/scripts/execution_target_policy.py agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_execution_target_policy.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py` — exit 0.
- `git diff --check` — 출력 없음.

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

