<!-- task=m-stream-evidence-gate-core/22+21_filter_observation_runtime plan=2 tag=REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME -->

# Plan - Filter observation 병렬·timeline 증거 결정화

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

구현과 테스트를 마친 뒤 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션에 실제 변경 내용과 모든 검증 stdout/stderr를 채우는 것이 필수다. active 파일을 그대로 두고 리뷰 준비 완료를 보고하며, 최종 판정·로그 아카이브·`complete.log`·task archive 이동은 code-review 스킬만 수행한다. 차단 시 구현 소유 evidence 필드에 정확한 blocker, 시도한 명령/출력, 재개 조건만 기록하고 사용자 질문·user-input 도구·control-plane stop 파일·다음 상태 분류를 수행하지 않는다.

## 배경

직전 후속은 non-ready epoch suppression과 all-complete 이후 단일 arbitration을 추가했지만, 두 ready evaluator의 동시 진입을 증명하지 않고 `time.Sleep`에 의존해 순차 평가 구현도 통과할 수 있다. runtime lifecycle 역시 종류별 총횟수만 엄격하고 위치별 kind/filter attribution은 느슨하므로, production 변경 없이 SDD S08/S12의 observation correlation과 parallel barrier 증거를 결정론적으로 닫는다.

## Archive Evidence Snapshot

- 직전 계획 증거: `agent-task/m-stream-evidence-gate-core/22+21_filter_observation_runtime/plan_cloud_G05_1.log`
- 직전 리뷰 증거: `agent-task/m-stream-evidence-gate-core/22+21_filter_observation_runtime/code_review_cloud_G05_1.log`
- 판정: FAIL (`Required=1`, `Suggested=0`, `Nit=0`)
- Required finding: runtime lifecycle의 epoch별 네 행이 start/evaluated 중 아무 종류나 허용되고 위치별 `filter_id`가 검증되지 않으며, coordinator fixture는 `time.Sleep`으로 시작을 추정해 순차 evaluator 구현도 통과하고 observation correlation fields를 단언하지 않는다.
- 영향 파일: `packages/go/streamgate/filter_observation_test.go`
- fresh 검증: focused/unit/race/gofmt/vet/diff 명령은 모두 통과했으며 `evidence_integrity_failure=false`다. 실패 원인은 실행 증거가 아니라 테스트 oracle의 완결성이다.
- 로드맵 계승: `Stream Evidence Gate Core` Milestone과 승인·잠금 해제된 SDD의 S08/S12만 보강한다. 특정 Milestone Task 완료를 주장하지 않으므로 `Roadmap Targets`는 두지 않고 roadmap checkbox를 직접 변경하지 않는다.

## 분석 결과

### 읽은 파일

- `agent-task/m-stream-evidence-gate-core/22+21_filter_observation_runtime/plan_cloud_G05_1.log`
- `agent-task/m-stream-evidence-gate-core/22+21_filter_observation_runtime/code_review_cloud_G05_1.log`
- `packages/go/streamgate/filter_observation.go`
- `packages/go/streamgate/filter_observation_test.go`
- `packages/go/streamgate/parallel_evaluation.go`
- `packages/go/streamgate/parallel_evaluation_test.go`
- `packages/go/streamgate/evaluation_contract.go`
- `packages/go/streamgate/runtime.go`
- `packages/go/streamgate/runtime_test.go`
- `agent-roadmap/current.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`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`

### SDD 기준

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`, 상태 `[승인됨]`, 잠금 `해제`.
- S08 / `filter-observation`: 같은 request timeline의 config/attempt/epoch/filter attribution과 raw-free lifecycle을 추적하는 observation evidence가 필요하다.
- S12 / `parallel-evaluation`: ready evaluator가 병렬 진입하고 complete outcome set 전에는 action하지 않으며 deferred/not-applicable은 평가 observation을 만들지 않아야 한다.
- Evidence Map의 S08 multi-consumer timeline과 S12 barrier/race/mixed outcome 요구를 각각 exact row oracle과 entered/release handshake로 구현 체크리스트 및 focused/race 검증에 반영한다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`와 `agent-test/local/platform-common-smoke.md`를 읽었다.
- PATH의 host Go provenance를 먼저 기록하고, 대상 package focused/unit/race, gofmt, vet, diff check를 `-count=1` 기준으로 fresh 실행한다.
- proto/config/wire 원본을 변경하지 않는 test-only 후속이므로 profile의 `make proto`와 Edge-Node transport/full-cycle 항목은 적용 대상이 아니다. package 검증은 프로젝트 domain rule과 기존 Go test layout을 fallback source로 사용한다.
- 외부 runner, provider, Docker, device가 필요하지 않아 별도 비-local 프리플라이트는 없다.

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

- `TestRuntimeObservation_LifecycleOrderAndCorrelation`: 총 13행과 kind별 횟수는 검증하지만 epoch filter 행의 정확한 kind 위치와 `filter_id`를 고정하지 않아 attribution 오염·start/evaluated 재배치를 놓친다.
- `TestGateCoordinatorObservation_ParallelCompletionAndDeltaSuppression`: non-ready outcome/suppression과 arbitration 1회는 검증하지만, evaluator 동시 진입을 관측하지 않아 순차 실행도 통과하고 네 observation의 sequence/correlation/epoch/filter row를 검증하지 않는다.
- `parallel_evaluation_test.go`의 기존 barrier fixture도 timer 대기에 의존하며 observation correlation을 다루지 않으므로 현재 Required의 대체 evidence가 아니다.

### 심볼 참조

- rename/remove되는 production symbol은 없다.
- test-local `controlledGateEvaluator`와 `mockGateArbiter` 참조는 `packages/go/streamgate/filter_observation_test.go` 내부에만 있다.

### 분할 판단

- exact runtime timeline과 deterministic parallel completion은 같은 S08/S12 observation evidence invariant를 공동으로 닫고 한 파일·한 package 검증으로 PASS하므로 하나의 compact plan으로 유지한다.

### 범위 결정 근거

- production `.go`, `parallel_evaluation_test.go`, runtime/recovery 동작, Edge sink, config/proto/contract는 변경하지 않는다.
- 기존 `TestRuntimeObservation_DeltaSuppression`은 request resolution exclusion을 보조 증거로 유지하되, Required 해결은 direct `EpochFilter` coordinator fixture에서 수행한다.

### 최종 라우팅

- `evaluation_mode=isolated-reassessment`, `finalizer=finalize-task-policy.sh`, `finalizer_mode=pair`.
- build/review closure: `scope_closed=true`, `context_closed=true`, `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`; capability gap 없음.
- build grade scores: scope=1, state/concurrency=2, blast=0, evidence=1, verification=1 → G05, base `local-fit`.
- review grade scores: scope=1, state/concurrency=2, blast=0, evidence=1, verification=1 → G05.
- `large_indivisible_context=false`; positive loop-risk는 `temporal_state`, `concurrent_consistency`, `boundary_contract` 3개다.
- recovery signals: `review_rework_count=2`, `evidence_integrity_failure=false`; build route는 `recovery-boundary`, cloud G05, `PLAN-cloud-G05.md`다.
- review route는 `official-review`, cloud G05, Codex `gpt-5.6-sol` xhigh, `CODE_REVIEW-cloud-G05.md`다.

## 구현 체크리스트

- [x] REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-1 runtime observation 13행을 exact kind/filter/epoch/correlation row로 단언한다.
- [ ] REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-2 ready evaluator 동시 진입·역순 완료·all-complete와 non-ready suppression을 timer 없이 단언한다.
- [x] REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-3 focused/unit/race/gofmt/vet/diff 검증을 fresh 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

### [REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-1] exact runtime observation rows

- 문제: `packages/go/streamgate/filter_observation_test.go:1372-1407`은 각 epoch의 네 행을 start/evaluated 중 하나로만 허용하고 attribution을 읽지 않아 정확한 lifecycle과 filter correlation을 고정하지 못한다.
- 해결 방법:

Before:

```go
for i := 1; i <= 4; i++ {
	k := obss[i].Kind()
	if k != ObservationKindFilterEvaluationStarted && k != ObservationKindFilterEvaluated {
		t.Errorf("observation[%d] kind = %s, want filter start or evaluated", i, k)
	}
}
```

After:

```go
want := []expectedObservationRow{
	{ObservationKindResponseStaged, "", 0},
	{ObservationKindFilterEvaluationStarted, "filter.alpha", 1},
	{ObservationKindFilterEvaluationStarted, "filter.beta", 1},
	{ObservationKindFilterEvaluated, "filter.alpha", 1},
	{ObservationKindFilterEvaluated, "filter.beta", 1},
	{ObservationKindArbitrationDecided, "", 1},
	{ObservationKindReleaseCommitted, "", 1},
	{ObservationKindFilterEvaluationStarted, "filter.alpha", 2},
	{ObservationKindFilterEvaluationStarted, "filter.beta", 2},
	{ObservationKindFilterEvaluated, "filter.alpha", 2},
	{ObservationKindFilterEvaluated, "filter.beta", 2},
	{ObservationKindArbitrationDecided, "", 2},
	{ObservationKindTerminalCommitted, "", 2},
}
```

- 수정 파일 및 체크리스트:
  - [ ] `packages/go/streamgate/filter_observation_test.go`: 13행 expected table에 sequence, kind, epoch, filter attribution, request/config/attempt correlation을 위치별로 비교한다.
  - [ ] lifecycle kind별 exact count와 response/arbitration/release/terminal 상세 단언을 유지한다.
- 테스트 작성: `TestRuntimeObservation_LifecycleOrderAndCorrelation`을 강화한다. 별도 production fixture는 추가하지 않는다.
- 중간 검증: `go test -count=1 ./packages/go/streamgate -run '^TestRuntimeObservation_LifecycleOrderAndCorrelation$'`가 통과해야 한다.

### [REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-2] deterministic parallel completion correlation

- 문제: `packages/go/streamgate/filter_observation_test.go:1586-1601`의 두 `time.Sleep`은 evaluator 진입 여부를 보장하지 않아 순차 실행 구현도 통과하며, `packages/go/streamgate/filter_observation_test.go:1643-1675`는 observation 종류 총수만 확인한다.
- 해결 방법:

Before:

```go
time.Sleep(50 * time.Millisecond)
if arb.count() != 0 { /* ... */ }
close(ch1)
time.Sleep(50 * time.Millisecond)
if arb.count() != 0 { /* ... */ }
```

After:

```go
waitEntered(t, entered, "filter.ready.1")
waitEntered(t, entered, "filter.ready.2")
close(release2)
waitCompleted(t, completed2)
if got := arb.count(); got != 0 { /* all-complete violation */ }
close(release1)
waitCompleted(t, completed1)
```

- 수정 파일 및 체크리스트:
  - [ ] `packages/go/streamgate/filter_observation_test.go`: evaluator별 entered/completed 신호와 독립 release 채널을 추가하고 두 evaluator 진입 후 역순 완료를 제어한다.
  - [ ] 첫 완료 뒤 arbitration 0회, 두 번째 완료 뒤 정확히 1회와 4-filter complete `EvaluationSet`을 단언한다.
  - [ ] ready observation 네 행을 exact sequence/kind/filter/request/config/attempt/epoch row로 비교한다.
  - [ ] unsubscribed=`not_applicable_for_epoch`, trigger-unready blocking=`deferred_by_requirement`, 두 non-ready filter의 start/evaluated 0건 단언을 유지한다.
- 테스트 작성: `TestGateCoordinatorObservation_ParallelCompletionAndDeltaSuppression`을 timer-free handshake fixture로 강화한다.
- 중간 검증: `go test -count=1 ./packages/go/streamgate -run '^TestGateCoordinatorObservation_ParallelCompletionAndDeltaSuppression$'`가 통과해야 한다.

### [REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-3] fresh verification evidence

- 문제: focused test가 통과해도 oracle 공백이 남았으므로 강화된 fixture와 package/race 검증을 같은 checkout에서 다시 증명해야 한다.
- 해결 방법: 아래 최종 검증을 순서대로 실행하고 실제 stdout/stderr와 exit 결과를 review stub에 기록한다. 캐시된 Go 결과는 사용하지 않는다.
- 수정 파일 및 체크리스트:
  - [ ] production 및 unrelated 파일이 변경되지 않았는지 확인한다.
  - [ ] Go provenance가 local rule과 일치하는지 기록한다.
  - [ ] focused/unit/race/gofmt/vet/diff 명령을 모두 성공시킨다.
- 테스트 작성: 추가 테스트 파일은 만들지 않는다. 항목 1/2에서 기존 fixture를 강화하는 것이 regression evidence다.
- 중간 검증: `git diff --check`가 clean이어야 한다.

## 의존 관계 및 구현 순서

REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-1/2 fixture 강화 → REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-3 fresh 검증 → review stub evidence 작성.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/go/streamgate/filter_observation_test.go` | REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-1, REVIEW_REVIEW_FILTER_OBSERVATION_RUNTIME-2 |

## 최종 검증

- `command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT`
- `go test -count=1 ./packages/go/streamgate -run '^(TestRuntimeObservation_LifecycleOrderAndCorrelation|TestRuntimeObservation_DeltaSuppression|TestGateCoordinatorObservation_ParallelCompletionAndDeltaSuppression)$'`
- `go test -count=1 ./packages/go/streamgate`
- `go test -race -count=1 ./packages/go/streamgate`
- `test -z "$(gofmt -l packages/go/streamgate/filter_observation_test.go)"`
- `go vet ./packages/go/streamgate/`
- `git diff --check`

기대 결과는 Go provenance가 host 설치와 일치하고 모든 검증 exit 0, gofmt 대상 없음, diff check clean이다.

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