<!-- task=m-stream-evidence-gate-core/04+01,03_codec_contract_fixtures plan=3 tag=REVIEW_REVIEW_REVIEW_TEST -->

# Stream Gate Failure Cause Exact Order Assertion 보완 계획

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

- 구현과 검증을 마친 뒤 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 내용과 출력으로 채우고, active 파일을 그대로 둔 채 review-ready를 보고한다.
- 종결 판정, log rename, `complete.log`, task archive는 code-review 전용이다.
- 선택된 Milestone `구현 잠금 > 결정 필요` 항목 때문에 막힌 경우에만 review stub의 `사용자 리뷰 요청`에 정확한 연결 대상과 evidence를 기록하고 멈춘다.
- 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하거나 `USER_REVIEW.md`를 만들지 않는다. 환경/secret/서비스 차단, 일반 범위 변경, 후속 에이전트가 보완할 수 있는 evidence 공백은 사용자 리뷰 사유가 아니다.

## 배경

현재 consumer fixture는 bounded cause chain의 길이와 첫/끝 원인, 필수 코드 존재를 확인하지만 가운데 두 원인의 값과 순서를 확인하지 않는다. 따라서 active plan이 요구한 exact latest-four order와 S21 완료 evidence를 증명하려면 네 위치를 모두 순서대로 대조해야 한다.

## 사용자 리뷰 요청 흐름

선택된 Milestone lock 결정만 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 형식으로 active review stub에 기록한다. 구현 중 직접 사용자 prompt는 금지하며, code-review가 요청의 정당성 검증과 실제 `USER_REVIEW.md` 작성을 소유한다.

## Archive Evidence Snapshot

- 이전 loop evidence:
  - `agent-task/m-stream-evidence-gate-core/04+01,03_codec_contract_fixtures/plan_local_G05_2.log`
  - `agent-task/m-stream-evidence-gate-core/04+01,03_codec_contract_fixtures/code_review_local_G06_2.log`
- 판정: FAIL
- 문제 수: Required 1, Suggested 0, Nit 0
- 핵심 문제:
  - latest-four 주석과 달리 index 0/3과 membership만 확인해 index 1/2가 잘못되거나 순서가 뒤바뀌어도 통과한다.
- 영향 파일: `packages/go/streamgate/consumer_contract_test.go`
- 검증 evidence:
  - Go 1.24.12 focused/full streamgate, Edge/Node transport, proto, import boundary, vet, gofmt/diff 검증은 PASS했다.
  - PASS 출력은 네 위치의 exact retained order를 증명하지 못한다.
- Roadmap carryover: `event-contract`의 S21 bounded cause-chain evidence를 같은 task에서 완결한다.

## 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:
  - `event-contract`: normalized event/base disposition, bounded failure cause와 endpoint별 single terminal result 계약
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `packages/go/streamgate/consumer_contract_test.go`
- `packages/go/streamgate/event.go`
- `packages/go/streamgate/terminal.go`
- `packages/go/streamgate/event_test.go`
- `packages/go/streamgate/terminal_test.go`
- `packages/go/streamgate/package_boundary_test.go`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/node/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`
- `agent-contract/outer/openai-compatible-api.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `agent-spec/input/openai-compatible-surface.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-task/archive/2026/07/m-stream-evidence-gate-core/01_event_contract_types/complete.log`
- `agent-task/archive/2026/07/m-stream-evidence-gate-core/03+01_event_contract_unit_tests/complete.log`
- `agent-task/m-stream-evidence-gate-core/04+01,03_codec_contract_fixtures/plan_local_G05_2.log`
- `agent-task/m-stream-evidence-gate-core/04+01,03_codec_contract_fixtures/code_review_local_G06_2.log`

### SDD 기준

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md`
- 상태: `[승인됨]`, SDD 잠금 `해제`
- 대상: S21 / `event-contract`
- Evidence Map: bounded failure-cause chain과 Chat/Responses host error codec fixture가 raw-free cause chain/endpoint-specific single-error를 증명해야 한다.
- 이번 후속은 S21 fixture의 latest-four 네 위치를 모두 대조해 bounded chain evidence를 완결한다. endpoint codec과 single terminal assertion은 변경하지 않고 회귀 검증한다.

### 테스트 환경 규칙

- `test_env`: local
- 적용 규칙: `agent-test/local/rules.md`, `agent-test/local/platform-common-smoke.md`
- 확인 환경: 기본 `go1.26.2`, `GOROOT=/config/opt/go`; module baseline과 호환되는 검증 toolchain은 `GOTOOLCHAIN=go1.24.12`, `GOROOT=/config/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.12.linux-arm64`
- 적용 명령: `make proto`, fresh focused/full streamgate, Edge/Node transport, deterministic import search, `go vet`, gofmt/diff check
- test-only assertion 보완이며 사용자 실행 경로와 production wire를 바꾸지 않으므로 repo Edge-Node 진단, 보조 E2E smoke, full-cycle 실제 구동은 이번 후속 범위에 필요하지 않다.

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

- existing generic coverage: `terminal_test.go`는 generic latest-four 순서를 검증한다.
- current consumer coverage gap: `consumer_contract_test.go`는 S21의 구체 원인 네 개 중 index 1/2를 대조하지 않아 endpoint consumer fixture의 exact order가 열려 있다.
- required closure: `chain.All()` 결과를 네 원인의 expected slice와 모든 index에서 대조한다.

### 심볼 참조

- rename/remove symbol: 없음
- 새 dependency: 없음

### 분할 판단

- split decision policy를 먼저 평가했다.
- 기존 dependent subtask `04+01,03_codec_contract_fixtures`의 동일 테스트 함수 안에서 한 ordered assertion만 보완한다. 별도 ownership/API/verification 경계가 없고 분할하면 같은 fixture에 인위적인 coordination만 추가하므로 단일 후속을 유지한다.
- predecessor `01`: `agent-task/archive/2026/07/m-stream-evidence-gate-core/01_event_contract_types/complete.log`로 충족
- predecessor `03`: `agent-task/archive/2026/07/m-stream-evidence-gate-core/03+01_event_contract_unit_tests/complete.log`로 충족

### 범위 결정 근거

- 수정 포함: `packages/go/streamgate/consumer_contract_test.go`
- 수정 제외: production `streamgate` source, Edge/Node codec, proto/config, contract/roadmap/spec 문서
- 현재 결함은 contract 구현이 아니라 consumer fixture의 exact-order assertion 공백이다.

### 최종 라우팅

- evaluation mode: `isolated-reassessment`
- build closures: scope/context/verification/evidence/ownership/decision 모두 `true`
- build scores: scope coupling 0, state concurrency 0, blast irreversibility 0, evidence diagnosis 1, verification complexity 1
- build result: `local`, `G02`, `PLAN-local-G02.md`
- review closures: scope/context/verification/evidence/ownership/decision 모두 `true`
- review scores: scope coupling 1, state concurrency 0, blast irreversibility 0, evidence diagnosis 1, verification complexity 1
- review result: `local`, `G03`, `CODE_REVIEW-local-G03.md`

## 구현 체크리스트

- [ ] `REVIEW_REVIEW_REVIEW_TEST-1` `chain.All()`의 네 원인을 expected latest-four slice와 index별로 대조해 전체 순서를 검증하고 기존 S09/S21 endpoint fixture assertions를 보존한다.
- [ ] `GOTOOLCHAIN=go1.24.12`로 focused/full streamgate와 Edge/Node transport 회귀를 fresh 실행하고 proto/import/vet/gofmt/diff 검증 결과를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_REVIEW_TEST-1] Exact latest-four cause order

- 문제: `packages/go/streamgate/consumer_contract_test.go:787-820`은 exact retained order를 주장하지만 index 0/3과 map membership만 확인한다. index 1/2가 뒤바뀌거나 다른 코드로 바뀌어도 테스트가 통과한다.
- 해결 방법:

Before (`packages/go/streamgate/consumer_contract_test.go:787`):

```go
firstCause, err := chain.At(0)
// ...
lastCause, err := chain.At(3)
// ...
retained := chain.All()
retainedCodes := make(map[string]bool)
```

After:

```go
expectedCodes := []string{
	"repetition_loop_detected",
	"filter_blocked",
	"validation_failed",
	"recovery_notice_translation_failed",
}
retained := chain.All()
if len(retained) != len(expectedCodes) {
	t.Fatalf("retained chain length = %d, want %d", len(retained), len(expectedCodes))
}
for i, want := range expectedCodes {
	if got := retained[i].Code(); got != want {
		t.Errorf("retained[%d].Code() = %q, want %q", i, got, want)
	}
}
```

- 기존 required-code 존재와 dropped prelude 부재 의미는 expected sequence 자체와 필요 최소 assertion으로 보존한다. 중복 map으로 order를 잃지 않는다.
- 수정 파일 및 체크리스트:
  - [ ] `packages/go/streamgate/consumer_contract_test.go`: exact four-position retained cause comparison
- 테스트 작성:
  - 기존 `TestReleaseSinkCommitsSingleExternalTerminal`을 강화한다.
  - 새 테스트 파일이나 production helper는 만들지 않는다.
- 중간 검증:
  - `GOTOOLCHAIN=go1.24.12 go test -count=1 -v ./packages/go/streamgate -run '^TestReleaseSinkCommitsSingleExternalTerminal$'`
  - 기대 결과: latest-four와 Chat SSE/Responses JSON/second commit subtest 전체 PASS

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/go/streamgate/consumer_contract_test.go` | REVIEW_REVIEW_REVIEW_TEST-1 |

## 최종 검증

1. `gofmt -d packages/go/streamgate/consumer_contract_test.go`
   - 기대 결과: stdout 없음
2. `GOTOOLCHAIN=go1.24.12 go test -count=1 -v ./packages/go/streamgate -run 'Test(OpenAIAndAgentCodecContractMatrix|ProviderErrorRetainsTerminalBaseDisposition|ReleaseSinkCommitsSingleExternalTerminal|StreamgateProductionImportsStayTransportAgnostic)$'`
   - 기대 결과: 대상 및 subtest 전체 PASS
3. `make proto`
   - 기대 결과: protobuf 생성 성공, `proto/gen/iop` 내용 변경 없음
4. `GOTOOLCHAIN=go1.24.12 go test -count=1 ./packages/go/streamgate`
   - 기대 결과: PASS
5. `GOTOOLCHAIN=go1.24.12 go test -count=1 ./apps/edge/internal/transport ./apps/node/internal/transport`
   - 기대 결과: PASS
6. `if rg --sort path -n '"iop/(apps/.*/internal|proto/gen/iop)"' packages/go/streamgate --glob '*.go' --glob '!**/*_test.go'; then exit 1; fi`
   - 기대 결과: stdout 없음, exit 0
7. `GOTOOLCHAIN=go1.24.12 go vet ./packages/go/streamgate`
   - 기대 결과: stdout 없음, exit 0
8. `git diff --check -- packages/go/streamgate proto/gen/iop`
   - 기대 결과: stdout 없음, exit 0

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
