<!-- task=m-agent-task-runtime-target-selector/07+06_context_review_recovery plan=3 tag=REFACTOR -->

# Plan - Deterministic archived official-review recovery

## 배경

`plan=2`는 official-review recovery decision을 canonical selector schema로 정규화했지만, official review에서 archive-only recovery의 source 선택이 `st_mtime`에 의존함을 확인했다. checkout·copy·touch로 mtime이 역전되면 suffix가 더 큰 최신 verdict review log 대신 과거 generation의 PLAN/work-unit을 재개한다. 이 후속은 archive protocol의 numeric suffix를 유일한 최신성 기준으로 사용하게 한다.

사용자 지정 cloud-G09 작업을 유지한다. worker와 review는 cloud Codex만 사용하며 Pi 또는 local model을 호출하지 않는다. 모든 Python 검증은 provider binary가 없는 `PATH=/usr/bin:/bin` simulation에서 수행한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md`
- Task ids: `context-failover`, `failure-budget`, `dispatch-integration`, `audit-tests`
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- `plan_cloud_G09_2.log`: canonical fixed official-review decision, route/work-unit recovery, nested audit evidence를 구현한 직전 계획.
- `code_review_cloud_G09_2.log`: FAIL Required. `latest_verdict_log()`가 mtime으로 log-only recovery source를 선택해, reversed-mtime fixture에서 logical latest `plan_cloud_G09_1.log` 대신 `plan_local_G08_0.log`/`plan-0`을 선택했다. focused/class/full suite는 PASS했지만 해당 archive-order boundary는 미검증이었다.
- `plan_local_G07_1.log`, `code_review_cloud_G07_1.log`: provider-deny guard 도입과 최초 schema 결함의 진단 근거. 이전 local/Pi 실행은 resume 대상이 아니다.

## 분석 결과

### archive identity 계약

- canonical archived review 이름은 `code_review_{lane}_G{grade}_{number}.log`이며 `{number}`는 task loop의 전역 증가 순번이다.
- `latest_verdict_log()`는 verdict가 있는 canonical review log만 후보로 하고 numeric suffix 최댓값을 선택해야 한다. mtime은 source 선택 기준이 될 수 없다.
- matching PLAN은 선택된 review의 `task/plan/tag` header identity로만 복원한다. malformed filename, verdict 부재, identity 불일치는 fail closed한다.
- active PLAN/CODE_REVIEW pair의 source-of-truth 우선순위는 바꾸지 않는다.

### 테스트 환경

`agent-test/local/rules.md`를 적용한다. focused/full unittest와 compile은 `PATH=/usr/bin:/bin`에서 실행하고 existing `invoke`/`build_command` provider-deny guard를 유지한다. archive ordering fixture는 temporary workspace에서 mtime을 의도적으로 역전시켜 suffix 선택만 검증하며 실제 provider command/session/process는 0건이어야 한다.

### 최종 라우팅

- `evaluation_mode=isolated-reassessment`, `finalizer=finalize-task-policy.sh`, `finalizer_mode=pair`.
- 사용자 지정 route override를 grade-boundary risk 재평가(`2/2/2/1/2`)에 반영한다.
- build: `cloud-G09`, `PLAN-cloud-G09.md`.
- review: official review `cloud-G09`, `CODE_REVIEW-cloud-G09.md`, `codex/gpt-5.6-sol xhigh`.

## 구현 체크리스트

- [ ] canonical archive review log의 numeric suffix로 latest verdict를 결정하고 mtime 의존을 제거한다.
- [ ] reversed-mtime multi-loop fixture에서 latest matching PLAN route/work-unit을 검증하고 malformed/non-verdict log를 배제한다.
- [ ] focused/class/full unittest, `py_compile`, `git diff --check`, provider command/session/process `0/0/0` evidence를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 변경과 출력으로 채운다.

## 구현 항목

### [REFACTOR-6] Archive suffix based recovery source

- 수정 파일: `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`
- canonical `code_review_*.log` filename을 strict parse하는 helper를 추가하거나 기존 matcher를 확장한다.
- `latest_verdict_log()`가 valid verdict를 가진 canonical log 중 suffix number가 가장 큰 하나만 반환하게 한다. mtime sorting과 non-canonical log fallback을 제거한다.
- `official_review_plan_source()`와 `matching_plan_log()`의 matching identity/fail-closed semantics는 유지한다.

### [TEST-4] Reversed-mtime archived loop recovery

- 수정 파일: `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`
- temporary workspace에 서로 다른 plan identity/route를 가진 archive loop 둘을 만들고, 최신 suffix review의 mtime을 과거로 설정한다.
- recovery task가 suffix가 큰 verdict의 matching PLAN lane/grade/work-unit을 선택하고 canonical decision을 생성하는지 assert한다.
- verdict 없는 canonical log와 malformed name은 candidate가 될 수 없으며, provider deny guard의 invocation/command count가 0인지 유지한다.

## 의존 관계 및 구현 순서

1. archive review filename parser와 numeric newest selection을 구현한다.
2. matching PLAN recovery가 suffix-selected review identity를 쓰는지 regression으로 고정한다.
3. provider-deny focused/class/full validation을 재실행하고 evidence를 작성한다.

## 수정 파일 요약

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

## 최종 검증

- `env PATH=/usr/bin:/bin python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py SelectorDispatcherIntegrationTest.test_review_recovery_and_runtime_audit_evidence -v` — reversed-mtime archive recovery와 provider deny PASS.
- `env PATH=/usr/bin:/bin python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py SelectorDispatcherIntegrationTest RepetitionLimitTest RouteDecisionPersistenceTest -v` — review/budget/generation/archive ordering regressions PASS.
- `env PATH=/usr/bin:/bin python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_*.py'` — fresh full suite PASS.
- `env PATH=/usr/bin:/bin 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 0.
- `git diff --check` — 출력 없음.
- 모든 검증 동안 real provider command/session/process=`0/0/0`.

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