<!-- task=m-stream-evidence-gate-core/08+02,05,06_filter_registry plan=3 tag=REVIEW_TEST -->

# Stream Gate Registry S11 검증 신뢰 복구 계획

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

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

## 배경

candidate별 resolver와 stable identity fence 자체는 구현됐지만, 이전 리뷰가 요구한 S11/coordinator assertions 중 일부가 이름과 주석만 바뀐 채 실제 조건을 검증하지 않는다. 동일 호스트의 transport 검증도 active review의 PASS 기록과 달리 표준 라이브러리 누락으로 실패하므로, 이번 follow-up은 production 동작을 넓히지 않고 누락된 assertion과 실제 검증 evidence만 복구한다.

## Archive Evidence Snapshot

- 직전 loop: `agent-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/plan_local_G06_2.log`, `agent-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/code_review_local_G06_2.log`
- 판정: `FAIL`; Required 2, Suggested 0, Nit 0.
- Required 요약: caller policy slice·provider별 `Applies` 차이·Evaluate full context·동일 non-empty batch assertions 누락, transport와 `make proto` 실제 출력 불일치.
- 영향 파일: `packages/go/streamgate/filter_registry_test.go`, active `CODE_REVIEW-*-G??.md` verification evidence.
- 실제 검증: candidate/identity focused race, S11 named tests, package race/vet/gofmt/import/proto/diff는 PASS. Edge/Node transport는 동일 host `/config/opt/go/src/crypto/internal/fips140cache` 누락으로 setup failure.
- production 확인: `packages/go/streamgate/filter_registry.go`의 candidate-aware resolver, disabled 조기 제외, snapshot/Begin/Resolve/Bind identity fence는 fresh 검증에서 통과했다.
- 선행 완료: `agent-task/archive/2026/07/m-stream-evidence-gate-core/02+01_evaluation_contract/complete.log`, `agent-task/archive/2026/07/m-stream-evidence-gate-core/05+02_parallel_evaluation_coordinator/complete.log`, `agent-task/archive/2026/07/m-stream-evidence-gate-core/06+01_evidence_tail/complete.log`

## Roadmap Targets

- Milestone: `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
- Task ids:
  - `filter-registry`: immutable generation/policy snapshot과 attempt/epoch-local active filter resolution
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `packages/go/streamgate/filter_registry.go`
- `packages/go/streamgate/filter_registry_test.go`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-ops/rules/common/rules-agent-spec.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-spec/index.md`
- `agent-contract/index.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-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/plan_local_G06_2.log`
- `agent-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/code_review_local_G06_2.log`

### SDD 기준

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`
- 상태: `[승인됨]`, SDD 잠금 `해제`, 사용자 리뷰 `없음`.
- 대상: Acceptance Scenario S11 / Milestone Task `filter-registry`.
- Evidence Map S11은 config-generation isolation, policy precedence, required capability admission, provider-switch와 duplicate-id tests를 요구한다.
- 따라서 caller slice mutation과 provider별 active/capability 차이를 실제로 assert하고, coordinator seam에서는 attempt-local context와 같은 immutable batch가 filter/Arbiter에 도달했다는 판정 evidence를 만든다.

### 테스트 환경 규칙

- `test_env`: local.
- `agent-test/local/rules.md`와 `agent-test/local/platform-common-smoke.md`를 읽었다.
- PATH host Go는 `/config/.local/bin/go` → `/config/opt/go/bin/go`, `go1.26.2`, `GOROOT=/config/opt/go`다. `GOROOT`/`GOTOOLCHAIN` override를 쓰지 않는다.
- fresh `-count=1` focused/package race, vet, `gofmt -d`, import boundary, `make proto`, proto/diff hygiene를 적용한다.
- Edge/Node transport는 현재 host 표준 라이브러리 `crypto/internal/fips140cache` 누락으로 setup failure다. 우회하거나 PASS로 재작성하지 않고 실제 stdout/stderr, exit code와 host Go 설치 복구 조건을 기록한다.
- production admission caller와 proto/config/wire를 바꾸지 않으므로 full-cycle 실제 구동은 후속 `vertical-slice` 범위다.
- 매칭되는 active agent-spec과 agent-contract 문서는 없다.

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

- policy immutability test는 snapshot에 전달한 slice를 보존하지 않아 element overwrite를 실행하지 않는다.
- provider re-resolution test는 두 provider 모두에 `Applies=true`라 서로 다른 resolved set/capability를 만들지 않는다.
- coordinator test는 Evaluate가 받은 endpoint/family/stable correlation을 capture하지 않고, filter/Arbiter가 받은 batch events와 `CapturedAt`을 비교하지 않는다.
- transport evidence는 동일 host의 fresh setup failure와 active review의 PASS 기록이 충돌한다.

### 심볼 참조

- production API rename/removal 없음.
- 변경 대상은 기존 test helper와 named test 내부이며 외부 call site는 없다.

### 분할 판단

- split decision policy를 routed filename 확정 전에 적용했다.
- 기존 subtask `08+02,05,06_filter_registry`를 유지하는 단일 plan이다. 누락 assertion은 같은 `filter_registry_test.go`의 S11/coordinator evidence이고, test와 그 실행 evidence를 분리하면 어느 쪽도 독립 PASS 산출물이 되지 않는다.
- API/production 변경, 별도 ownership, 다른 환경 경계가 없으므로 추가 split은 인위적이다.
- predecessor `02`, `05`, `06`은 Archive Evidence Snapshot의 archived `complete.log`로 충족됐다.

### 범위 결정 근거

- 수정은 `packages/go/streamgate/filter_registry_test.go`와 active review evidence로 제한한다.
- `packages/go/streamgate/filter_registry.go`의 resolver/identity 동작, proto/config, Edge/Node admission/dispatch, roadmap 문서는 변경하지 않는다.
- unrelated dirty worktree와 sibling subtask는 건드리지 않는다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`
- build:
  - closures: scope/context/verification/evidence/ownership/decision 모두 `true`
  - 근거: 한 test file의 네 assertion과 실제 명령 출력으로 범위·판정이 닫히며 fresh reviewer evidence가 충돌 지점을 확정했다.
  - grade scores: scope coupling 1, state/concurrency 1, blast/irreversibility 0, evidence diagnosis 2, verification complexity 1
  - lane/result: `local`, `G05`, `PLAN-local-G05.md`
- review:
  - closures: scope/context/verification/evidence/ownership/decision 모두 `true`
  - 근거: 실제 slice/provider/context/batch assertions와 fresh stdout/stderr를 정적·동적으로 재검증할 수 있다.
  - grade scores: scope coupling 1, state/concurrency 1, blast/irreversibility 0, evidence diagnosis 2, verification complexity 1
  - lane/result: `local`, `G05`, `CODE_REVIEW-local-G05.md`

## 구현 체크리스트

- [ ] `REVIEW_TEST-1` caller policy slice mutation, provider별 `Applies` 차이, Evaluate full context와 filter/Arbiter 동일 non-empty batch assertions를 실제 조건으로 복구한다.
- [ ] `REVIEW_TEST-2` host Go 기준 fresh 검증을 재실행하고 transport setup failure를 포함한 실제 stdout/stderr와 exit code를 그대로 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

### [REVIEW_TEST-1] S11과 coordinator assertion 복구

- 문제:
  - `filter_registry_test.go:471-487`은 익명 slice를 snapshot에 넘긴 뒤 지역 변수만 재할당한다.
  - `filter_registry_test.go:631-642`는 두 provider 모두에 `Applies=true`라 provider switch로 active set이 달라지지 않는다.
  - `filter_registry_test.go:60-85`, `725-729`, `741-745`, `811-829`는 Evaluate full context와 filter/Arbiter batch event/`CapturedAt` identity를 capture·비교하지 않는다.
- 해결 방법:
  - caller-owned `policies` slice를 snapshot에 넘기고 snapshot 생성 뒤 `policies[0]`/`policies[1]`을 overwrite한다.
  - provider `Applies`를 한 provider에만 true로 만들고 resolved set과 required capabilities가 provider별로 달라짐을 assert한다.
  - `capturedContext`에 endpoint/family/stable correlation을 포함하고 Evaluate에서 받은 batch와 Arbiter가 받은 batch를 각각 capture한다. 고정 timestamp의 non-empty text event를 넣어 `CapturedAt`, event kind/channel/timestamp/payload, terminal/commit state를 입력과 비교한다.
- Before (`filter_registry_test.go:471`):

```go
snap, _ := NewFilterRegistrySnapshot("gen-1", regs, []FilterPolicyLayer{p1, p2})
p1 = replacement1
p2 = replacement2
```

- After:

```go
policies := []FilterPolicyLayer{p1, p2}
snap, _ := NewFilterRegistrySnapshot("gen-1", regs, policies)
policies[0] = replacement1
policies[1] = replacement2
```

- 수정 파일 및 체크리스트:
  - [ ] `packages/go/streamgate/filter_registry_test.go`: actual slice overwrite, provider-specific negative set/capability, full context와 same-batch assertions
- 테스트 작성:
  - `TestFilterRegistryPolicyIsFilterScopedAndSnapshotImmutable`: 전달 slice element overwrite 뒤 기존 snapshot 불변과 새 snapshot 변경을 확인한다.
  - `TestFilterRegistryReresolvesProviderSpecificApplies`: 적용 provider와 비적용 provider의 resolved/capability 차이를 확인한다.
  - `TestResolvedFilterAdapterPassesFullContextThroughCoordinator`: Evaluate full scalar와 filter/Arbiter가 받은 동일 logical non-empty batch를 확인한다.
- 중간 검증:
  - `go test -race -count=1 -v ./packages/go/streamgate -run '^Test(FilterRegistry(PolicyIsFilterScopedAndSnapshotImmutable|ReresolvesProviderSpecificApplies|UsesValidatedHoldRequirement)|ResolvedFilterAdapterPassesFullContextThroughCoordinator)$'`
  - 기대 결과: actual mutation/provider negative/full-context/same-batch assertions가 선택돼 PASS하고 race가 없다.

### [REVIEW_TEST-2] 실제 검증 출력 복구

- 문제:
  - archived `code_review_local_G06_2.log:304-327`은 `make proto`를 무출력, transport를 PASS로 기록했지만 reviewer fresh 결과와 불일치한다.
- 해결 방법:
  - 계획의 모든 명령을 동일 PATH host Go에서 다시 실행하고 active review에 실제 stdout/stderr와 exit code를 붙인다.
  - transport가 계속 setup failure면 우회하지 않고 `/config/opt/go/src/crypto/internal/fips140cache` 누락과 host Go 설치 복구를 재개 조건으로 기록한다.
- Before (`code_review_local_G06_2.log:320`):

```text
ok iop/apps/edge/internal/transport
ok iop/apps/node/internal/transport
```

- After:

```text
FAIL iop/apps/edge/internal/transport [setup failed]
FAIL iop/apps/node/internal/transport [setup failed]
resume: repair the host Go installation
```

- 수정 파일 및 체크리스트:
  - [ ] `agent-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/CODE_REVIEW-local-G05.md`: 실제 명령 출력, exit code, blocker/재개 조건
- 테스트 작성:
  - 새 behavior test는 작성하지 않는다. `REVIEW_TEST-1`의 회귀와 기존 package suite를 fresh 실행한다.
- 중간 검증:
  - `command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT`
  - `make proto`
  - `go test -count=1 ./apps/edge/internal/transport ./apps/node/internal/transport`
  - 기대 결과: stdout/stderr와 exit code를 요약 없이 기록하고 setup failure를 PASS로 분류하지 않는다.

## 의존 관계 및 구현 순서

1. `REVIEW_TEST-1`에서 test가 실제 S11/coordinator 조건을 판정하도록 만든다.
2. `REVIEW_TEST-2`에서 같은 checkout과 host Go로 전체 검증 evidence를 다시 수집한다.
3. predecessor `02`, `05`, `06`은 archived `complete.log`로 충족됐다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/go/streamgate/filter_registry_test.go` | REVIEW_TEST-1 |
| `agent-task/m-stream-evidence-gate-core/08+02,05,06_filter_registry/CODE_REVIEW-local-G05.md` | REVIEW_TEST-2, 구현 evidence |

## 최종 검증

1. `command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT`
   - 기대 결과: PATH host Go와 실제 GOROOT 기록.
2. `gofmt -d packages/go/streamgate/filter_registry.go packages/go/streamgate/filter_registry_test.go`
   - 기대 결과: stdout 없음.
3. `go test -race -count=1 -v ./packages/go/streamgate -run '^Test(FilterRegistry(PolicyIsFilterScopedAndSnapshotImmutable|ReresolvesProviderSpecificApplies|UsesValidatedHoldRequirement)|ResolvedFilterAdapterPassesFullContextThroughCoordinator)$'`
   - 기대 결과: actual mutation/provider negative/full-context/same-batch assertions PASS.
4. `go test -race -count=1 -v ./packages/go/streamgate -run '^TestFilterRegistry(CandidateScopedActiveResolution|DisabledFilterSkipsContractCalls|RejectsIdentityMutationAtBoundaries)$'`
   - 기대 결과: candidate/disabled/identity regression PASS.
5. `go test -count=1 ./packages/go/streamgate -run '^Test(FilterContext|FilterRegistry|FilterBase|ResolvedFilter)'`
   - 기대 결과: focused suite PASS.
6. `go test -race -count=1 ./packages/go/streamgate`
   - 기대 결과: package PASS, race 없음.
7. `go vet ./packages/go/streamgate`
   - 기대 결과: stdout 없음.
8. `go list -f '{{range .Imports}}{{println .}}{{end}}' ./packages/go/streamgate | LC_ALL=C sort`
   - 기대 결과: 표준 라이브러리만 출력.
9. `make proto`
   - 기대 결과: 성공하고 실제 stdout을 기록하며 생성물 추가 diff 없음.
10. `go test -count=1 ./apps/edge/internal/transport ./apps/node/internal/transport`
    - 기대 결과: PASS 또는 현재 host Go setup failure 원문·exit code·복구 조건 기록. 실패를 성공으로 재작성하지 않는다.
11. `git diff --check -- packages/go/streamgate proto/gen/iop`
    - 기대 결과: stdout 없음.
12. `git status --short -- proto/gen/iop`
    - 기대 결과: stdout 없음.

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