<!-- task=m-stream-evidence-gate-core/03+01_event_contract_unit_tests plan=0 tag=API -->
<!-- plan-model=GPT-5 -->


# Stream Gate Event Contract Unit Tests 구현 계획

## 구현 에이전트 규칙

- Runtime이 encoded predecessor를 확인한 뒤에만 이 pair를 전달한다. 전달받은 Worker는 `agent-task/**`나 archive를 검색하지 않는다.
- 아래 세 test 파일만 수정하고 구현 체크리스트와 검증 명령을 따른다.
- review stub의 구현 소유 필드와 명령 출력만 채운다.
- `review-ready`를 보고하고 종료한다. code-review, archive, terminal file 작성, 다음 agent 시작은 금지한다.

## 배경

`01_event_contract_types`가 만드는 transport-agnostic 공개 계약은 enum/payload validation, defensive copy, bounded failure cause, terminal mutual exclusion을 직접 검증해야 후속 codec/host fixture가 안정적으로 소비할 수 있다. 이 child는 production source를 수정하지 않고 공개 API의 정상·경계 단위 테스트만 만든다.

## 구현 범위

- Write set:
  - `packages/go/streamgate/event_test.go`
  - `packages/go/streamgate/filter_contract_test.go`
  - `packages/go/streamgate/terminal_test.go`
- `NormalizedEvent`, `BaseEventDisposition`, `EvidenceBatch`, `FailureCauseChain`, `TerminalResult`, `ReleaseSink`의 정상·경계 계약을 test-only consumer로 검증한다.
- 참고 경로: `packages/go/audit/audit_test.go`, `apps/edge/internal/openai/common_types.go`, `apps/edge/internal/openai/server.go`, `apps/edge/internal/openai/chat_stream_session_test.go`.
- SDD `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`의 `S09`, `S21`에 필요한 event/disposition, defensive copy, bounded cause, terminal validation evidence를 작성한다.
- `agent-test/local/rules.md`를 따르며 Go 검증은 `-count=1`로 실행한다. `make proto` toolchain 부재는 성공이 아니라 차단 evidence로 기록한다.
- Production source, Edge/Node codec, proto, config, contract 문서는 수정하지 않는다. Fake codec/host와 import-boundary 검사는 `04+01,03_codec_contract_fixtures`에 남긴다.

## 구현 체크리스트

- [ ] `API-2` event/disposition, evidence immutability, decision/outcome, 최대 4단계 cause, terminal result와 ReleaseSink compile contract의 정상/경계 테스트를 작성한다.
- [ ] 계획에 명시한 local 검증 명령을 fresh cache 조건으로 실행하고 stdout/stderr를 review stub에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채우고 review-ready를 보고한 뒤 현재 실행을 종료한다. code-review를 실행하거나 다음 에이전트를 시작하지 않는다.

### [API-2] 계약 validation과 불변성 테스트

- 문제:
  - 공통 stream contract의 mutable alias, invalid enum, unsafe header, raw cause 유입을 막는 테스트가 없다.
  - 기존 endpoint 테스트는 string error만 다루므로 공통 terminal payload 경계를 보장하지 않는다.
- 해결 방법:
  - table-driven tests로 모든 event kind/base disposition과 invalid payload 조합을 고정한다.
  - response-start header와 evidence pending/look-behind의 입력 및 accessor 반환값을 변경해 원본 snapshot 유지 여부를 검증한다.
  - hop-by-hop/`Content-Length` staged metadata 거부를 검증한다.
  - failure cause code/id validation, 4개 cap, append immutability, terminal success/error mutual exclusion을 검증한다.
  - compile assertion으로 fake sink가 `ReleaseSink`를 구현하게 하되 single-terminal 동작은 closure sibling의 host fixture에서 검증한다.
- Before:

```text
packages/go/streamgate/*_test.go do not exist
```

- After (test inventory):

```go
func TestNormalizedEventConstructorsAndBaseDisposition(t *testing.T)
func TestResponseStartRejectsUnsafeHeaders(t *testing.T)
func TestEvidenceBatchDefensivelyCopiesInputsAndAccessors(t *testing.T)
func TestFilterOutcomeSeparatesNotApplicableAndDeferred(t *testing.T)
func TestFailureCauseChainCapsAtFour(t *testing.T)
func TestTerminalResultValidation(t *testing.T)
func TestReleaseSinkContractCompiles(t *testing.T)
```

- 수정 파일 및 체크리스트:
  - [ ] `packages/go/streamgate/event_test.go`: event table, invalid shape, staged header copy/validation
  - [ ] `packages/go/streamgate/filter_contract_test.go`: evidence copy, decision/outcome/intent validation
  - [ ] `packages/go/streamgate/terminal_test.go`: cause cap/sanitization, terminal validation, sink compile assertion
- 테스트 작성: 위 7개 테스트를 반드시 작성한다. 실제 Edge/Node codec integration test는 이 child에서 작성하지 않는다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/go/streamgate/event_test.go` | API-2 |
| `packages/go/streamgate/filter_contract_test.go` | API-2 |
| `packages/go/streamgate/terminal_test.go` | API-2 |

## 최종 검증

1. `gofmt -d packages/go/streamgate/event_test.go packages/go/streamgate/filter_contract_test.go packages/go/streamgate/terminal_test.go`
   - 기대 결과: stdout 없음
2. `make proto`
   - 기대 결과: protobuf 생성 성공. toolchain이 없으면 차단 evidence로 기록
3. `go test -count=1 ./packages/go/streamgate`
   - 기대 결과: PASS
4. `go test -count=1 ./apps/edge/internal/transport ./apps/node/internal/transport`
   - 기대 결과: PASS
5. `git diff --check -- packages/go/streamgate proto/gen/iop`
   - 기대 결과: stdout 없음

검증 결과를 review stub에 기록하고 review-ready를 보고한 뒤 현재 실행을 종료한다. code-review를 실행하거나 다음 에이전트를 시작하지 않는다.
