<!-- task=m-agent-task-runtime-target-selector/09+08_admission_quota_batch plan=2 tag=REVIEW_REFACTOR -->

# Plan - Admission batch probe identity와 zero-probe 경계 보정

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

선행 `08+07_selfcheck_policy`의 archived `complete.log`와 아래 Archive Evidence Snapshot을 기준으로 두 Required만 보정한다. 구현과 검증을 끝낸 뒤 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 내용과 원문 출력으로 채우고 active 파일은 그대로 둔 채 review 준비 완료만 보고한다. 종결은 code-review skill 전용이다. 차단되면 정확한 원인, 시도한 명령/출력, 재개 조건만 구현 에이전트 소유 evidence에 기록하며 사용자 질문, user-input 도구, control-plane stop file, 다음 상태 분류, archive/log 이동, `complete.log`, roadmap 수정은 하지 않는다.

## 배경

기존 구현은 focused 3건과 전체 241건을 통과했지만 admission probe 대상과 full probe key의 경계를 충분히 보존하지 못했다. 야간 local-first와 공식 review가 불필요한 quota probe를 실행하고, aggregate가 command/profile 축이 다른 key를 하나로 합친다. 이 follow-up은 SDD S11의 batch observation 범위와 계획의 zero-probe/full-key 불변조건만 복구한다.

## Archive Evidence Snapshot

- 이전 task: `agent-task/m-agent-task-runtime-target-selector/09+08_admission_quota_batch`
- 이전 plan: `agent-task/m-agent-task-runtime-target-selector/09+08_admission_quota_batch/plan_local_G07_1.log`
- 이전 review: `agent-task/m-agent-task-runtime-target-selector/09+08_admission_quota_batch/code_review_cloud_G07_1.log`
- 판정: FAIL
- 발견사항: Required 2, Suggested 0, Nit 0.
- Required 1: `dispatch.py:1575-1610`이 official review와 local-first 뒤 cloud fallback까지 probe 대상으로 수집한다. 재현 결과 야간 `local-G08`은 Gemini probe 1회, official review는 Codex probe 1회를 실행하지만 review decision의 quota id/time은 `None`이다.
- Required 2: `select_execution_target.py:544-555`가 `(adapter,target,command/profile,required_caps)`의 세 번째 축을 버린다. command/profile만 다른 입력 key 2개가 probe 1회로 축약됨을 재현했다.
- 영향 파일: `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py`, `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`, `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py`, `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`.
- 검증 evidence: 기존 `ThroughputQuotaBatchTest` 3건 PASS, 전체 Python suite 241건 PASS, `py_compile`/`git diff --check` PASS. 누락 변형 focused reproducer는 `night_local_probe_calls=[('agy', 'Gemini 3.6 Flash (Medium)')]`, `review_probe_calls=[('codex', 'gpt-5.6-sol')]`, `input_keys=2/probe_calls=1`을 출력했다.
- Roadmap carryover: 승인 SDD S11/`throughput-policy`의 admission batch slice다. 이 child는 Milestone Task 전체 완료를 주장하지 않으므로 `Roadmap Targets`는 계속 생략한다.

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/testing-smoke.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md`
- `agent-roadmap/sdd/automation-runtime-bridge/agent-task-runtime-target-selector/SDD.md`
- `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/scripts/dispatch.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`
- `apps/node/cmd/node/quota_probe.go`
- `apps/node/internal/adapters/cli/status/quota.go`
- `agent-task/m-agent-task-runtime-target-selector/09+08_admission_quota_batch/plan_local_G07_1.log`
- `agent-task/m-agent-task-runtime-target-selector/09+08_admission_quota_batch/code_review_cloud_G07_1.log`

### SDD 기준

- SDD: `agent-roadmap/sdd/automation-runtime-bridge/agent-task-runtime-target-selector/SDD.md`, 상태 `[승인됨]`, 잠금 해제.
- 대상: S11 / Milestone Task `throughput-policy`.
- Evidence Map: 동시 dispatch와 batch quota snapshot 테스트가 같은 batch id/time, unique observation, target별 격리와 불필요한 probe 부재를 증명해야 한다.
- 이 child는 S11 중 batch observation만 소유한다. 구현 체크리스트는 full key 보존과 worker-initial zero-probe 경계로 역산하고, 최종 검증은 focused provider/dispatcher 회귀와 전체 Python suite로 고정한다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`와 testing route의 `agent-test/local/testing-smoke.md`를 읽었다.
- provider process를 실행하지 않는 dispatcher unit/integration simulation 규칙을 적용한다. 모든 quota probe는 fake seam에서 호출 identity/count를 검증하고 실제 `iop-node`, provider CLI, network 실행을 금지한다.
- `testing-smoke`의 Edge-Node full-cycle/live preflight는 이 follow-up의 selector/dispatcher 내부 admission key 경계를 실행하지 않으므로 적용 명령으로 사용하지 않는다. downstream audit closure가 전체 runtime evidence를 소유한다.
- fallback 검증은 현재 checkout의 Python unittest manifest, `py_compile`, `git diff --check`다. test-rule 구조는 완전하며 유지보수는 필요하지 않다.

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

- 기존 동일 target/mixed target 테스트는 adapter+target만 비교하고 command/profile 축을 검증하지 않는다.
- 기존 local zero-probe 테스트는 `local-G05`만 사용해 cloud fallback이 뒤에 있는 야간 `local-G07/G08`을 놓친다.
- 공식 review가 batch key 수집에서 제외되는지와 review decision이 batch snapshot을 소비하지 않는 고정 정책을 검증하지 않는다.

### 심볼 참조

- `probe_candidate_quota`: selector initial/failover와 `QuotaBatchProvider.aggregate`, `test_select_execution_target.py`, `test_dispatch.py` mock call sites가 있다. command/profile 인자를 분리하면 모든 호출을 호환성 있게 갱신한다.
- `QuotaBatchProvider`: `dispatch.py:1616-1623`의 batch 생성과 새 selector 단위 테스트가 소비한다.
- `build_admission_batch_snapshot`: dry-run, live admission pass, `ThroughputQuotaBatchTest`가 소비한다.
- 삭제/rename symbol은 없다.

### 분할 판단

- 기존 shared task group은 `m-agent-task-runtime-target-selector`, 현재 subtask는 `09+08_admission_quota_batch`다.
- predecessor `08+07_selfcheck_policy`는 `agent-task/archive/2026/07/m-agent-task-runtime-target-selector/08+07_selfcheck_policy/complete.log`로 충족됐다.
- 두 Required는 하나의 probe-key producer/consumer 계약과 같은 focused matrix를 공유하며 별도 child로 나누면 동일 call path를 중복 수정한다. 기존 subtask 내부 단일 follow-up이 가장 작은 독립 review 단위다.

### 범위 결정 근거

- target semaphore 제거는 `10+09_target_cap_removal`, probe failure/unknown 격리는 `11+10_unknown_isolation`, 최종 audit는 `12+08,11_audit_closure` 범위이므로 수정하지 않는다.
- Go quota producer, roadmap/SDD, testing rules, inventory, 다른 task artifact와 `packages/go/streamgate/**`는 변경하지 않는다.
- 기존 unrelated dirty worktree를 보존하고 이 follow-up의 네 파일과 active pair만 다룬다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`
- finalizer=`finalize-task-policy.sh`, finalizer_mode=`pair`; build/review status=`routed`.
- build closures: `scope_closed=true`(두 재현과 S11 경계가 고정됨), `context_closed=true`(selector/dispatcher와 두 test file로 닫힘), `verification_closed=true`(focused fake-probe matrix와 전체 suite), `evidence_trusted=true`(기존 PASS와 실패 재현 모두 현재 checkout에서 실행됨), `ownership_closed=true`(testing domain과 현재 split이 소유), `decision_closed=true`(Milestone 결정 필요 없음).
- review closures: `scope_closed=true`, `context_closed=true`, `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`; 동일 source/test/reproducer로 판정 가능하다.
- build route_basis=`local-fit`; capability_gap=`none`; grade floor=`none`.
- build loop-risk: ordered_transitions=`state_count=2/adverse_paths=2`, concurrent_consistency=`actor_count>=2/exactly-once shared snapshot`, boundary_contract=`selector+dispatcher와 dry/live consumers`, structured_interpretation=`4-tuple dedup/aggregate merge`, variant_product=`stage × candidate order × command/profile`; matched signatures=`concurrent_consistency,boundary_contract,structured_interpretation,variant_product`, triggered=`true`.
- build scores(scope_coupling/state_concurrency/blast_irreversibility/evidence_diagnosis/verification_complexity)=`2/2/1/1/1`, final=`local-G07`, filename=`PLAN-local-G07.md`.
- review route_basis=`official-review`; capability_gap=`none`; grade floor=`none`; execution=`codex/gpt-5.6-sol xhigh`.
- review scores(scope_coupling/state_concurrency/blast_irreversibility/evidence_diagnosis/verification_complexity)=`2/2/1/1/1`, final=`cloud-G07`, filename=`CODE_REVIEW-cloud-G07.md`.

## 구현 체크리스트

- [ ] `(adapter,target,command/profile,required_caps)` full key를 dedup과 실제 probe argv까지 보존하고 command/profile 변형별 정확히 1회 관측 회귀를 통과한다.
- [ ] admission batch key 수집을 최초 worker 선택에 필요한 ordered cloud 후보로 제한하고 야간 local-first, official review, resume/selfcheck가 probe 0회인 회귀를 통과한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

## 구현 항목

### [REVIEW_REFACTOR-1] Full probe key 보존

- 문제: `select_execution_target.py:544-563`이 4-tuple의 command/profile을 버리고 adapter를 `--command`로 재사용해 서로 다른 key를 하나로 합친다.
- 해결 방법:

```python
# Before: select_execution_target.py:544
adapter, target_name, _, required_caps = key[:4]
k = (adapter, target_name, tuple(required_caps))
probe_candidate_quota(adapter=adapter, target=target_name, ...)
```

```python
# After
adapter, target_name, probe_command, required_caps = key
k = (adapter, target_name, probe_command, tuple(required_caps))
probe_candidate_quota(
    adapter=adapter,
    target=target_name,
    probe_command=probe_command,
    ...,
)
```

  `probe_candidate_quota`는 selector identity인 adapter와 Go probe의 `--command` 값을 분리하되 기존 직접 호출은 adapter fallback으로 호환한다. aggregate target evidence에는 child snapshot/reason과 probe command를 보존한다.
- 수정 파일 및 체크리스트:
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py`: full key 정규화, dedup, command 전달.
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py`: `QuotaBatchProviderTest.test_command_profile_axis_is_not_deduplicated` 추가.
- 테스트 작성: 동일 adapter+target/required caps에 command `agy`와 `antigravity`를 주입해 fake probe가 각각 1회 호출되고 batch child evidence가 두 observation을 보존하는지 검증한다.
- 중간 검증: `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py QuotaBatchProviderTest -v` — full-key/argv matrix PASS.

### [REVIEW_REFACTOR-2] Initial worker zero-probe 경계

- 문제: `dispatch.py:1575-1610`이 review를 포함하고 모든 cloud candidate를 수집해 무조건 eligible한 local-first 뒤 fallback과 quota를 소비하지 않는 official review까지 probe한다.
- 해결 방법:

```python
# Before: dispatch.py:1575
if stage not in {"worker", "review"}:
    continue
for cand in pol_dec.candidates:
    if cand.execution_class == "local_model":
        continue
    collect(cand)
```

```python
# After
if stage != "worker" or has_persisted_worker_decision(state):
    continue
for cand in pol_dec.candidates:
    if cand.execution_class == "local_model":
        break
    collect_full_probe_key(cand)
```

  worker ordered policy에서 local candidate는 quota와 무관하게 항상 eligible이므로 그 뒤 후보는 initial admission에 필요하지 않다. review/selfcheck/resume은 batch probe 대상에서 제외하고 cloud-first worker는 같은 batch snapshot id/time을 공유한다.
- 수정 파일 및 체크리스트:
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`: worker-initial key collection과 ordered stop 경계.
  - [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: `ThroughputQuotaBatchTest`에 야간 local-G07/G08, official review, resume/selfcheck zero-probe 및 cloud-first shared identity assertions 추가.
- 테스트 작성: timezone-aware 고정 KST 시각과 fake quota provider를 사용한다. actual provider command/subprocess가 호출되면 test-owned deny seam으로 실패시킨다.
- 중간 검증: `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ThroughputQuotaBatchTest -v` — zero-probe와 batch identity matrix PASS.

## 의존 관계 및 구현 순서

1. predecessor `08+07_selfcheck_policy`는 archived `complete.log`로 충족됐다.
2. REVIEW_REFACTOR-1에서 full key 전달 계약을 먼저 고정한 뒤 REVIEW_REFACTOR-2의 dispatcher 수집 경계를 그 계약에 맞춘다.
3. 후속 `10+09_target_cap_removal`과 `11+10_unknown_isolation`의 active files나 구현은 수정하지 않는다.

## 수정 파일 요약

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

## 최종 검증

- `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py QuotaBatchProviderTest -v` — full probe key와 command argv 회귀 PASS.
- `python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ThroughputQuotaBatchTest -v` — local/review/resume/selfcheck zero-probe와 shared batch identity PASS.
- `python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_*.py'` — fresh process 전체 suite PASS; cache output은 허용하지 않는다.
- `python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py` — exit 0.
- `git diff --check` — 출력 없음.

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