<!-- task=m-stream-evidence-gate-core/21+14,19_filter_observation_contract plan=3 tag=REVIEW_FILTER_OBSERVATION_CONTRACT -->

# Plan - FilterObservation recovery strategy/resume 계약 정합성

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

구현·테스트·검증 evidence만 소유한다. 체크리스트와 검증을 완료한 뒤 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션에 실제 내용과 stdout/stderr를 채우고 active pair를 그대로 둔 채 review ready를 보고한다. 차단되면 정확한 blocker, 시도한 명령/출력, 재개 조건만 구현 소유 evidence에 기록한다. 사용자 질문, user-input 도구, `USER_REVIEW.md`, 상태 분류, log archive, `complete.log`, roadmap 수정은 수행하지 않는다.

## 배경

`ObservationRecoveryInfo`는 known strategy와 resume mode를 개별 검증하지만 실제 `RecoveryPlan`이 강제하는 strategy→resume-mode 조합을 확인하지 않는다. 이 때문에 exact/schema recovery가 post-commit continuation처럼 기록되거나 continuation recovery가 replace-attempt처럼 기록될 수 있어 SDD S08 timeline의 recovery 의미가 canonical runtime plan과 달라진다.

## Archive Evidence Snapshot

- 이전 task path: `agent-task/m-stream-evidence-gate-core/21+14,19_filter_observation_contract/`
- 종료 pair: `plan_local_G06_2.log`, `code_review_cloud_G06_2.log`
- 판정: FAIL; Required 1, Suggested 0, Nit 0
- 문제 요약: `ObservationRecoveryInfo.Validate`가 `exact_replay|schema_repair + continue_stream`과 `continuation_repair|managed_continuation + replace_attempt`를 허용해 canonical `RecoveryPlan.Validate`와 모순된다.
- 영향 파일: `packages/go/streamgate/filter_observation.go`, `packages/go/streamgate/filter_observation_test.go`
- 실제 검증: host Go `1.26.2`; `make proto`, focused test, `go test -count=1 ./packages/go/streamgate`, `go test -race -count=1 ./packages/go/streamgate`, `gofmt -l`, `git diff --check`, `go vet ./packages/go/streamgate/` 모두 PASS. 기존 테스트는 strategy/resume 반대 조합을 생성하지 않아 semantic gap을 검출하지 못했다.
- Roadmap carryover: approved SDD S08의 observation contract foundation만 보완한다. full lifecycle hook/runtime/sink는 sibling `22`~`24` 범위이며 이 pair에는 `Roadmap Targets`가 없다.
- 좁은 재열람 허용: `agent-task/m-stream-evidence-gate-core/21+14,19_filter_observation_contract/plan_local_G06_2.log`, `agent-task/m-stream-evidence-gate-core/21+14,19_filter_observation_contract/code_review_cloud_G06_2.log`

## 분석 결과

### 읽은 파일

- 규칙/환경: `agent-ops/rules/project/rules.md`, `agent-ops/rules/project/domain/platform-common/rules.md`, `agent-ops/rules/project/domain/testing/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/filter_observation.go`, `packages/go/streamgate/filter_observation_test.go`
- canonical 연결 계약: `packages/go/streamgate/recovery_plan.go:679-699`, `packages/go/streamgate/recovery_plan.go:819-832`
- 현재 loop evidence: 위 `Archive Evidence Snapshot`의 두 log
- split 선행 evidence: `agent-task/archive/2026/07/m-stream-evidence-gate-core/14+13_recovery_execution/complete.log`, `agent-task/archive/2026/07/m-stream-evidence-gate-core/19+18_core_runtime_loop/complete.log`

### SDD 기준

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`; 상태 `[승인됨]`, 잠금 해제.
- 대상 Scenario: S08 / Milestone Task `filter-observation`.
- Evidence Map: multi-consumer observation timeline이 plan strategy/resume mode와 raw absence를 canonical runtime 의미로 보존해야 한다.
- 적용: 이 pair는 S08 전체 완료가 아니라 recovery summary의 strategy/resume contract만 닫는다. exact/schema→replace와 continuation/managed→continue의 정상·반대 조합, 그리고 각 resume mode의 commit-state 결합을 checklist와 fresh package/race 검증으로 고정한다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`와 `agent-test/local/platform-common-smoke.md`를 읽었다.
- 현재 checkout의 PATH 첫 Go(`/config/.local/bin/go` → `/config/opt/go/bin/go`, Go `1.26.2`)를 유지하고 fresh `-count=1` package/race test를 사용한다.
- profile setup인 `make proto`를 실행한다. proto/config/wire나 사용자 실행 경로는 바꾸지 않으므로 transport/full-cycle 실제 구동은 적용하지 않는다.
- fallback 검증은 프로젝트 규칙의 target package test, `go vet`, `gofmt`, `git diff --check`다. `<확인 필요>` 값은 없다.

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

- 기존 `TestObservationRecoveryInfo_SharedAttemptCoupledToResumeMode`는 shared attempt id만 검증하고 네 strategy와 resume mode의 canonical 결합을 검증하지 않는다.
- 기존 `TestFilterObservation_KindStateMatrix`는 exact-replace와 continuation-continue 대표 조합만 다루며 schema/managed 및 반대 resume 조합을 생성하지 않는다.
- 새 표 기반 회귀에서 네 strategy의 정상/반대 resume mode와 observation commit state를 함께 검증해야 한다.

### 심볼 참조

- renamed/removed symbol: 없음.
- `NewObservationRecoveryInfo` 호출은 현재 `packages/go/streamgate/filter_observation_test.go`에만 있으며 production hook은 sibling `22`/`23`이 후속 연결한다.

### 분할 판단

- split policy를 평가했다. 이미 Milestone split subtask `21+14,19_filter_observation_contract`이며 한 validator와 같은 test matrix를 원자적으로 보완하는 작업이라 추가 분할은 인위적이다.
- predecessor `14`: `agent-task/archive/2026/07/m-stream-evidence-gate-core/14+13_recovery_execution/complete.log`로 충족.
- predecessor `19`: `agent-task/archive/2026/07/m-stream-evidence-gate-core/19+18_core_runtime_loop/complete.log`로 충족.

### 범위 결정 근거

- 수정 범위는 `packages/go/streamgate/filter_observation.go`와 `packages/go/streamgate/filter_observation_test.go`뿐이다.
- `recovery_plan.go`의 canonical matrix는 변경하지 않고 observation validation이 동일 조합을 강제하도록 한다. runtime/hook/Edge sink는 sibling `22`~`24` 범위라 수정하지 않는다.
- agent-contract index와 agent-spec index에는 이 in-process observation value contract에 매칭되는 활성 문서가 없다. agent-contract, agent-spec, roadmap은 갱신하지 않는다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`; finalizer=`finalize-task-policy.sh`; finalizer_mode=`pair`.
- build closures: scope/context/verification/evidence/ownership/decision 모두 true. 근거는 두 파일의 확정 failing matrix, approved S08, canonical `RecoveryPlan` switch, fresh package/race output, 선행 완료와 sibling 범위 분리, Milestone 결정 필요 없음이다.
- build route: `local-fit`; capability gap: none; scores=`scope_coupling=1,state_concurrency=1,blast_irreversibility=1,evidence_diagnosis=1,verification_complexity=1`; lane/G=`local/G05`; filename=`PLAN-local-G05.md`.
- build loop-risk: recovery strategy 4종×resume mode 2종×commit state 3종의 closed state matrix와 invalid recovery paths로 `temporal_state`, `boundary_contract`, `variant_product`가 matched; concurrent actors와 structured interpretation은 없음. triggered=true이며 route에는 영향을 주지 않았다.
- review closures: 모두 true; source, canonical plan validator, SDD와 focused/full/race output을 독립 대조할 수 있다.
- review route: `official-review`; capability gap: none; scores=`1,1,1,1,1`; lane/G=`cloud/G05`; filename=`CODE_REVIEW-cloud-G05.md`; target=`Codex gpt-5.6-sol xhigh`.

## 구현 체크리스트

- [x] [REVIEW_FILTER_OBSERVATION_CONTRACT-1] observation recovery strategy→resume-mode와 commit-state 불변식을 canonical `RecoveryPlan`과 일치시키고 네 strategy의 정상/반대 조합 회귀 및 fresh local 검증을 완료한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

### [REVIEW_FILTER_OBSERVATION_CONTRACT-1] Recovery strategy/resume closed matrix

- 문제: `packages/go/streamgate/filter_observation.go:362-381`은 strategy와 resume mode를 개별 enum으로만 검사해 `packages/go/streamgate/recovery_plan.go:687-697,820-832`가 금지하는 exact/schema continuation과 continuation/managed replacement를 유효한 observation summary로 만든다.
- 해결 방법:

```go
// Before: known enum과 shared attempt id coupling만 검사한다.
if _, ok := knownRecoveryStrategies[r.strategy]; !ok { ... }
if err := r.resumeMode.Validate(); err != nil { ... }

// After: canonical RecoveryPlan과 같은 closed matrix를 먼저 강제한다.
switch r.strategy {
case RecoveryStrategyExactReplay, RecoveryStrategySchemaRepair:
    require(RecoveryResumeModeReplaceAttempt)
case RecoveryStrategyContinuationRepair, RecoveryStrategyManagedContinuation:
    require(RecoveryResumeModeContinueStream)
}
```

  - [x] `ObservationRecoveryInfo.Validate`가 exact/schema→`replace_attempt`, continuation/managed→`continue_stream`만 허용한다.
  - [x] 기존 shared attempt id와 `validateObservationRecoveryCommitState` 결합을 유지해 valid summary가 observation kind별 commit state에서도 동일 의미를 가진다.
- 수정 파일 및 체크리스트:
  - [x] `packages/go/streamgate/filter_observation.go`: strategy/resume closed matrix validation과 구체적 오류를 추가했다.
  - [x] `packages/go/streamgate/filter_observation_test.go`: `TestObservationRecoveryInfo_StrategyResumeModeMatrix`를 추가하고 `TestFilterObservation_KindStateMatrix`를 네 strategy의 정상/반대 commit 조합으로 확장했다.
- 테스트 작성: 표 기반으로 네 strategy 각각의 canonical resume mode 성공, 반대 resume mode 실패, valid summary의 올바른/반대 commit state를 검증한다. 기존 shared attempt id 경계도 계속 통과해야 한다.
- 중간 검증: `go test -count=1 ./packages/go/streamgate -run '^(TestObservationRecoveryInfo_(SharedAttemptCoupledToResumeMode|StrategyResumeModeMatrix)|TestFilterObservation_KindStateMatrix)$'`가 PASS해야 한다.

## 의존 관계 및 구현 순서

`14`, `19` 완료 → strategy/resume validator → full matrix regression → fresh package/race/static 검증. sibling `22`/`23` hook은 이 contract PASS 뒤 소비한다.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/go/streamgate/filter_observation.go` | REVIEW_FILTER_OBSERVATION_CONTRACT-1: canonical strategy/resume validation |
| `packages/go/streamgate/filter_observation_test.go` | REVIEW_FILTER_OBSERVATION_CONTRACT-1: four-strategy resume/commit matrix regression |

## 최종 검증

- [x] `command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT` → `/config/.local/bin/go` → `go1.26.2 linux/arm64`
- [x] `make proto` → PASS (no errors)
- [x] `go test -count=1 ./packages/go/streamgate -run '^(TestObservationRecoveryInfo_(SharedAttemptCoupledToResumeMode|StrategyResumeModeMatrix)|TestFilterObservation_KindStateMatrix)$'` → PASS (0.002s)
- [x] `go test -count=1 ./packages/go/streamgate` → PASS (0.872s)
- [x] `go test -race -count=1 ./packages/go/streamgate` → PASS (1.923s)
- [x] `test -z "$(gofmt -l packages/go/streamgate/filter_observation.go packages/go/streamgate/filter_observation_test.go)"` → gofmt OK
- [x] `git diff --check` → (no output, clean)
- [x] `go vet ./packages/go/streamgate/` → (no output, clean)

CODE_REVIEW-cloud-G05.md의 구현 에이전트 소유 섹션(계획 대비 변경 사항, 주요 설계 결정, 검증 결과)을 실제 구현 내용과 stdout/stderr로 채웠다.
