<!-- task=m-stream-evidence-gate-core/14+13_recovery_execution plan=1 tag=REVIEW_RECOVERY_EXECUTION -->

# Plan - Recovery Coordinator 필수 Evidence 보강

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

이 plan은 테스트와 검증 evidence 보강만 소유한다. 아래 검증을 실행하고 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션에 실제 변경 내용과 stdout/stderr를 기록한 뒤 active 파일을 그대로 두고 review-ready로 보고한다. 막히면 정확한 blocker, 시도한 명령/출력, 재개 조건만 구현 소유 evidence에 남긴다. 사용자에게 질문하거나 user-input 도구를 호출하거나 control-plane stop 파일을 만들거나 다음 상태를 분류하지 않는다. log archive, `complete.log`, verdict와 task archive는 code-review 스킬 전용이다.

## 배경

Recovery Coordinator 구현과 전체 unit/race 회귀는 통과했지만, 최초 리뷰에서 계획 RECOVERY-3와 승인 SDD Evidence Map의 S14·S20 필수 fixture 두 개가 누락된 것으로 판정됐다. production 동작을 넓히지 않고 Arbiter→Coordinator 연결의 single-dispatch 증거와 abort-timeout barrier 증거를 전용 테스트에 추가해 `recovery-coordinator` 완료 근거를 닫는다.

## Archive Evidence Snapshot

- Prior task: `agent-task/m-stream-evidence-gate-core/14+13_recovery_execution`
- Archived plan: `agent-task/m-stream-evidence-gate-core/14+13_recovery_execution/plan_cloud_G09_0.log`
- Archived review: `agent-task/m-stream-evidence-gate-core/14+13_recovery_execution/code_review_cloud_G09_0.log`
- Verdict: FAIL
- Findings: Required 2, Suggested 0, Nit 0.
- Required evidence gap 1: S14 `two violations -> one plan/dispatch`가 Arbiter-only와 Coordinator-only tests로 분리돼 연결 seam이 검증되지 않았다.
- Required evidence gap 2: S20 abort failure는 검증됐지만 blocking abort의 deadline/timeout 뒤 zero downstream side effect가 검증되지 않았다.
- Affected file: `packages/go/streamgate/recovery_coordinator_test.go`.
- Verification evidence: host Go `/config/.local/bin/go` -> `/config/opt/go/bin/go`, Go `1.26.2`, `GOROOT=/config/opt/go`; fresh package unit/race와 `git diff --check`는 통과했다.
- Roadmap carryover: `recovery-coordinator`; SDD S14와 S20 Evidence Map을 모두 충족해야 check-on-pass할 수 있다.
- Narrow reread allowed when exact prior context is needed: 위 archived plan/review 두 파일만 읽는다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md`
- Milestone link: [Stream Evidence Gate Core](agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
- Task ids:
  - `recovery-coordinator`: Recovery Coordination과 Request Rebuild coordinator
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md`
- `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md`
- `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`
- `packages/go/streamgate/recovery_coordinator.go`
- `packages/go/streamgate/recovery_coordinator_test.go`
- `packages/go/streamgate/recovery_plan.go`
- `packages/go/streamgate/recovery_plan_test.go`
- `packages/go/streamgate/decision_arbiter.go`
- `packages/go/streamgate/decision_arbiter_test.go`
- `packages/go/streamgate/parallel_evaluation.go`
- `packages/go/streamgate/parallel_evaluation_test.go`
- `packages/go/streamgate/stream_release.go`

### SDD 기준

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`; 상태 `[승인됨]`, 잠금 해제, 사용자 리뷰 없음.
- 대상 Task: `recovery-coordinator`.
- S14는 같은 epoch의 두 retryable violation을 deterministic하게 하나로 고른 뒤 cycle당 plan/idempotency key/dispatch 하나만 허용하도록 요구한다. Evidence Map은 simultaneous intent와 one plan/dispatch assertion을 필수로 둔다.
- S20은 current attempt abort timeout/failure에서 next attempt를 시작하지 않는 fixture를 요구한다. Evidence Map은 no-overlapping-live-attempt assertion을 필수로 둔다.
- 구현 checklist와 검증은 이 두 누락 행만 역산한다. S18/S23/S24와 기존 fault/managed budget 회귀는 최초 구현과 package suite가 이미 제공하며 범위를 확장하지 않는다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`와 `agent-test/local/platform-common-smoke.md`를 읽었다.
- host PATH의 Go 정체를 먼저 기록하고 검증 중 toolchain을 바꾸지 않는다.
- matched profile의 proto setup/Edge-Node transport unit은 proto/config/wire 변경용이며 이번 test-only streamgate 범위에는 적용하지 않는다.
- fallback verification source는 현재 package test layout, 최초 plan의 streamgate unit/race 명령, 승인 SDD S14/S20 Evidence Map이다.
- fresh evidence가 중요하므로 모든 Go test는 `-count=1`을 사용한다. 외부 서비스, Docker, port, secret은 필요 없다. 테스트 규칙 유지보수도 필요 없다.

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

- 두 violation deterministic 선택 자체: `decision_arbiter_test.go`가 커버한다.
- single cycle ordering/binding/dispatch 자체: `recovery_coordinator_test.go`가 커버한다.
- 두 violation의 실제 Arbiter result가 Coordinator까지 이어져 one plan/dispatch가 되는 연결: 미커버, 이번 plan에서 추가한다.
- 즉시 abort error의 downstream barrier: 기존 failure table이 커버한다.
- blocking abort가 caller deadline으로 timeout된 뒤 prepare/rebuild/dispatch zero, usage zero, snapshot release one인 경로: 미커버, 이번 plan에서 추가한다.
- production behavior 변경: 없음. 새 fixture가 기존 동작과 불일치를 드러내면 소스 수정으로 확장하지 않고 blocker evidence를 공식 리뷰에 남긴다.

### 심볼 참조

- renamed/removed symbol: 없음.
- 새 production API 또는 dependency: 없음.

### 분할 판단

- split decision policy를 먼저 적용했다.
- 두 fixture는 같은 `recovery_coordinator_test.go`, 같은 `recovery-coordinator` SDD closure, 같은 package verification을 공유하는 test-evidence 보강이다.
- API/호출부, domain, ownership, 외부 환경, 독립 배포 경계가 없고 둘을 나누면 같은 active follow-up과 full unit/race closure를 중복한다. 기존 split task 경로 안의 단일 plan이 더 안전하다.
- predecessor `13`은 `agent-task/archive/2026/07/m-stream-evidence-gate-core/13+11,12_recovery_plan_contract/complete.log`의 PASS로 충족됐다.

### 범위 결정 근거

- 수정 허용: `packages/go/streamgate/recovery_coordinator_test.go`의 두 필수 fixture와 필요한 test-local helper만.
- 제외: `recovery_coordinator.go`, recovery plan API, Gate Coordinator, StreamReleaser, host/endpoint 조립, roadmap, contract/config, agent-spec. 최초 리뷰에서 production correctness/API defect는 발견되지 않았고 task `19`가 실제 gate-cycle 조립을 소유한다.
- dispatcher-cancel race, endpoint error 직렬화, vertical slice는 이번 Required finding이 아니므로 추가하지 않는다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`
- finalizer: `finalize-task-policy.sh`
- finalizer_mode: `pair`
- build closures: scope/context/verification/evidence/ownership/decision 모두 `true`. 근거는 한 test file의 두 명시 fixture, 읽은 source/test/SDD, 재현 가능한 local commands, 다른 dirty sibling 보존, 미해결 사용자 결정 없음이다.
- build route_basis: `local-fit`; capability_gap: none.
- build grade_scores: `scope_coupling=1`, `state_concurrency=1`, `blast_irreversibility=0`, `evidence_diagnosis=1`, `verification_complexity=1`; grade `G04`.
- build loop-risk observations:
  - ordered_transitions: `state_count=6`, adverse paths=`simultaneous_intent`, `abort_timeout`; Arbiter→plan→abort→prepare/rebuild→dispatch ordering을 assertion한다.
  - concurrent_consistency: `actor_count=2`; caller deadline과 blocking controller 사이에서 no downstream/exactly-once release를 검증한다.
  - boundary_contract: `component_count=4`, `consumer_count=1`; Arbiter, RecoveryCoordinator, AttemptController, Rebuilder/Dispatcher의 immutable selection·single-dispatch 경계다.
  - structured_interpretation: mechanisms/hazards 없음.
  - variant_product: `independent_axis_count=2`, `combination_verification_required=false`; 두 독립 fixture로 닫는다.
  - matched signatures: `temporal_state`, `concurrent_consistency`, `boundary_contract`; triggered `true`이나 route/grade에는 사용하지 않았다.
- build output: `PLAN-local-G04.md`.
- review closures: scope/context/verification/evidence/ownership/decision 모두 `true`; official reviewer가 두 named tests와 full unit/race output을 독립 대조할 수 있다.
- review route_basis: `official-review`; capability_gap: none.
- review grade_scores: `scope_coupling=1`, `state_concurrency=1`, `blast_irreversibility=0`, `evidence_diagnosis=1`, `verification_complexity=1`; grade `G04`.
- review output: `CODE_REVIEW-cloud-G04.md`; official target Codex `gpt-5.6-sol` xhigh.
- finalizer 출력과 canonical filenames가 일치한다.

## 구현 체크리스트

- [ ] REVIEW_RECOVERY_EXECUTION-1 두 filter violation을 같은 `EvaluationSet`에서 arbitrate한 결과로 coordinator를 실행하고 winner contributor와 cycle당 plan/abort/rebuild/dispatch 각 1회를 검증한다.
- [x] REVIEW_RECOVERY_EXECUTION-2 blocking abort가 deadline으로 끝날 때 prepare/rebuild/dispatch 0회, fault usage 0, preparation snapshot release 1회, 기존 binding 유지가 성립함을 검증한다.
- [x] REVIEW_RECOVERY_EXECUTION-3 focused test, streamgate unit/race, gofmt/diff 검증을 fresh execution으로 수행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

### [REVIEW_RECOVERY_EXECUTION-1] S14 simultaneous intent 연결 fixture

- 문제: `packages/go/streamgate/recovery_coordinator_test.go:341`부터의 coordinator tests는 `coordinatorArbitration`으로 단일 결과를 직접 만들고, `packages/go/streamgate/decision_arbiter_test.go:939`의 multiple candidate test는 Arbiter winner만 확인한다. S14의 두 violation에서 실제 one plan/dispatch까지 이어지는 연결 근거가 없다.
- 해결 방법:

```go
// Before: packages/go/streamgate/recovery_coordinator_test.go:357
input := coordinatorCycleInput(t, "plan.one", RecoveryStrategyExactReplay)
result, err := coordinator.Execute(context.Background(), input)

// After: two filter outcomes -> Arbitrate -> the same Execute input
arbitration, err := Arbitrate(ctx, batch, twoViolationSet)
input.Arbitration = arbitration
result, err := coordinator.Execute(ctx, input)
```

- 수정 파일 및 체크리스트:
  - [x] `packages/go/streamgate/recovery_coordinator_test.go`: `TestRecoveryCoordinatorTwoViolationsSinglePlan`을 추가한다.
  - [x] 서로 다른 stable filter/rule과 deterministic priority/tie-break winner를 구성한다.
  - [ ] result contributor가 winner와 일치하고 recorder가 `abort -> rebuild -> dispatch` 한 묶음만 기록하며 dispatcher/rebuilder가 각 1회임을 assertion한다.
- 테스트 작성: 위 named integration-style unit fixture를 작성한다. 기존 package-local evidence/filter/outcome helpers를 재사용하고 새 production helper/API를 만들지 않는다.
- 중간 검증: `go test -count=1 ./packages/go/streamgate -run '^TestRecoveryCoordinatorTwoViolationsSinglePlan$'` — PASS, one plan/dispatch assertions 실행.

### [REVIEW_RECOVERY_EXECUTION-2] S20 abort-timeout barrier fixture

- 문제: `packages/go/streamgate/recovery_coordinator_test.go:485`의 abort failure case는 controller가 즉시 error를 반환한다. blocking abort가 context deadline으로 끝나는 S20 경로의 zero downstream/zero usage/snapshot release evidence가 없다.
- 해결 방법:

```go
// Before: immediate failure only
controller := &coordinatorController{err: hostErr}

// After: controller blocks until the Execute context deadline
ctx, cancel := context.WithTimeout(context.Background(), boundedTimeout)
defer cancel()
controller := &coordinatorController{started: started, release: neverClosed}
```

- 수정 파일 및 체크리스트:
  - [x] `packages/go/streamgate/recovery_coordinator_test.go`: `TestRecoveryCoordinatorAbortTimeoutBlocksDownstream`을 추가한다.
  - [x] preparation이 필요한 continuation input과 snapshot/preparer를 사용해 abort-timeout 뒤 preparer/rebuilder/dispatcher가 모두 0회임을 검증한다.
  - [x] `ErrRecoveryAbortFailed`, recorder의 abort→snapshot.release 순서, usage 0, release 1회, current binding 유지와 single plan ledger를 assertion한다.
- 테스트 작성: caller deadline으로 deterministic하게 unblock되는 fixture를 작성한다. sleep 기반 관찰 대신 controller의 `started` channel과 context timeout을 사용한다.
- 중간 검증: `go test -count=1 ./packages/go/streamgate -run '^TestRecoveryCoordinatorAbortTimeoutBlocksDownstream$'` — PASS, no downstream side effect assertions 실행.

### [REVIEW_RECOVERY_EXECUTION-3] Evidence와 회귀 검증

- 문제: 최초 검증은 package 전체 성공만 보여 주며 S14/S20 named fixture가 실제 실행됐음을 구분하지 못했다.
- 해결 방법: Go 정체 확인, gofmt, 두 named focused tests, 전체 unit/race, deterministic symbol search, diff check를 fresh 실행하고 stdout/stderr를 review stub에 그대로 남긴다.
- 수정 파일 및 체크리스트:
  - [x] repo-local 임시 도구나 생성물을 만들지 않는다.
  - [x] 아래 최종 검증 명령을 순서대로 실행하고 실제 출력을 기록한다.
- 테스트 작성: 별도 테스트는 추가하지 않는다. REVIEW_RECOVERY_EXECUTION-1/2가 필수 regression fixtures다.
- 중간 검증: `gofmt -l packages/go/streamgate/recovery_coordinator_test.go` — 출력 없음.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/go/streamgate/recovery_coordinator_test.go` | REVIEW_RECOVERY_EXECUTION-1/2/3 |

## 최종 검증

- `command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT` — host Go 정체가 local rule과 일치한다.
- `gofmt -l packages/go/streamgate/recovery_coordinator_test.go` — 출력 없음.
- `go test -count=1 ./packages/go/streamgate -run 'TestRecoveryCoordinator(TwoViolationsSinglePlan|AbortTimeoutBlocksDownstream)'` — 두 fixture PASS.
- `go test -count=1 ./packages/go/streamgate` — PASS.
- `go test -race -count=1 ./packages/go/streamgate` — PASS.
- `rg --sort path -n '^func TestRecoveryCoordinator(TwoViolationsSinglePlan|AbortTimeoutBlocksDownstream)' packages/go/streamgate/recovery_coordinator_test.go` — 정확히 두 named fixture가 출력된다.
- `git diff --check` — 출력 없음.

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

## 의존 관계 및 구현 순서

REVIEW_RECOVERY_EXECUTION-1과 2는 독립적으로 작성할 수 있다. 두 fixture를 모두 추가한 뒤 REVIEW_RECOVERY_EXECUTION-3 전체 검증을 수행한다. 선행 subtask `13`은 archived `complete.log`로 충족됐다.

## 분할 결정

기존 `14+13_recovery_execution` split task 안의 test-evidence follow-up이다. 같은 파일·Task id·검증 경계를 공유하고 별도 API/도메인/환경 경계가 없으므로 추가 split은 하지 않는다.
