<!-- task=m-stream-evidence-gate-core/06+01_evidence_tail plan=0 tag=API -->

# Code Review Reference - API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## 개요

date=2026-07-24
task=m-stream-evidence-gate-core/06+01_evidence_tail, plan=0, tag=API

## Archive Evidence Snapshot

- 선행 완료: `agent-task/archive/2026/07/m-stream-evidence-gate-core/01_event_contract_types/complete.log`
- 선행 결과: normalized event, immutable `EvidenceBatch`, release/terminal 계약이 PASS로 종결됐다.
- 구현 기준: SDD 명칭/필드 일치, UTF-8 입력 경계, tool fragment keying, sink 성공 뒤 cursor/look-behind 확정.
- Roadmap carryover: S01/S02 core evidence는 이 plan에서 만들고, S19 cancel→terminal/no-release evidence와 `evidence-tail` 완료 이벤트는 `07+01,06_commit_boundary`에서 닫는다.
- 구현자는 위 경로 외의 `agent-task/archive/**`를 다시 탐색할 필요가 없다.

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.

1. 판정을 append한다.
2. `CODE_REVIEW-local-G06.md` → `code_review_local_G06_0.log`, `PLAN-local-G05.md` → `plan_local_G05_0.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-stream-evidence-gate-core/06+01_evidence_tail/`로 이동한다. WARN/FAIL이면 code-review skill이 요구하는 다음 filesystem state를 완전히 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| API-1 FilterHoldRequirement와 keyed Unicode evidence state | [x] |
| API-2 Transactional release confirmation과 recovery state | [x] |

## 구현 체크리스트

- [x] `API-1` SDD와 동일한 `FilterHoldRequirement`, enforcement-aware channel plan 및 tool-fragment keyed Unicode rune evidence state를 구현하고 200/500 threshold, Korean chunk, terminal/fragment trigger를 테스트한다.
- [x] `API-2` prepared release/partial confirmation, overflow no-release signal, terminal pending discard, replace reset/continuation preserve를 구현하고 stale·중복 transition을 테스트한다.
- [x] 호스트 `go` 기준 focused/fresh/race/vet 및 공통 profile 명령을 실행하고 blocker를 포함한 실제 출력을 기록한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_0.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_local_G05_0.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-stream-evidence-gate-core/06+01_evidence_tail/`를 `agent-task/archive/YYYY/MM/m-stream-evidence-gate-core/06+01_evidence_tail/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-stream-evidence-gate-core/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [x] WARN/FAIL이면 code-review skill의 판정에 맞는 다음 filesystem state를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

1. `EvidenceTailSignalOverflow` 상수명을 `EvidenceTailSignalBufferOverflow`로 변경: 타입 `EvidenceTailSignalOverflow`과의 이름 충돌 회피. SDD 명세 변경이 아닌 식별자 충돌 해결.
2. `EvidencePlan`에 `BlockingRequirementFor(channel) (FilterHoldRequirement, bool)` 접근자 추가: `evidence_tail.go` 내부에서 `evidencePlan.blockingRequirements`를 직접 접근할 때 Go 컴파일러가 `EvidencePlan` 필드로 해석하는 문제 해결. 계획에서 명시한 `evidencePlan` private 필드 구조는 유지.
3. `compileEvidencePlan`에 `req.IsBlocking()` 추가 체크: `none` mode가 `blocksRelease: true`로 바인딩되더라도 hold에 합성되지 않도록. 계획의 "non-blocking/none은 release를 막지 않게 한다" 요구사항 반영.
4. `Append`의 signal 미초기화 시 `EvidenceTailSignal(""`)` 반환 문제를 `EvidenceTailSignalNone` 초기화로 수정. 계획의 signal enum 일치 검증.
5. `ConfirmRelease` 토큰 매칭을 `fmt.Sprintf("prepared-%d-%d", 0, ...)` 하드코딩에서 `tokenToChannel` 맵 조회로 변경. 계획의 "opaque prepared token" 요구사항에 부합.

## 주요 설계 결정

1. `FilterHoldBinding`의 `blocksRelease`와 `FilterHoldRequirement.IsBlocking()`을 AND 조건으로 사용: caller가 명시한 enforcement flag와 requirement mode의 양쪽이 blocking일 때만 channel hold에 합성. observe-only filter가 실수로 blocking으로 작용하는 것을 방지.
2. `tokenToChannel` 맵을 `EvidenceTail`에 추가: prepared release 토큰에서 channel을 역으로 찾을 때 O(1) 조회. 맵은 `ResetForReplace`, `PrepareContinuation`, `DiscardPendingForTerminal`, `ConfirmRelease` 후 제거로 lifetime 관리.
3. overflow는 `maxBufferRunes` 초과 시 pending에 추가하지 않고 즉시 signal 반환: SDD "partial output release 금지" 요구사항 구현. 계획의 "No release is produced"와 일치.
4. fragment completion은 channel+toolCallID 조합으로 격리: 하나의 tool fragment 완료 결과가 다른 tool에 영향을 주지 않음. 계획의 "tool fragment keyed" 요구사항 구현.
5. `PrepareContinuation`은 `committedLookBehind`만 보존: recovery continuation에서 이미 release된 safe prefix를 다음 attempt가 이어서 쓸 수 있도록. exact/schema replay는 허용하지 않음 (이 foundation plan의 책임 범위).

## 리뷰어를 위한 체크포인트

- public hold type과 mode/field matrix가 SDD `FilterHoldRequirement`와 일치하는지 확인한다.
- observe-only/none binding이 channel hold를 만들지 않고 blocking requirement만 deterministic하게 합성되는지 확인한다.
- invalid UTF-8을 release하지 않고, valid Korean chunks를 Unicode rune으로 세는지 확인한다.
- fragment state가 channel+tool-call ID로 격리되는지 확인한다.
- prepare 시 cursor가 변하지 않고 zero/partial/full confirm만 실제 released prefix를 반영하는지 확인한다.
- terminal discard가 pending/prepared release를 downstream write 없이 폐기하는지 확인한다.
- 이 foundation PASS가 Roadmap `evidence-tail`을 조기 완료시키지 않는지 확인한다.

## 검증 결과

> 구현 에이전트는 각 명령의 실제 stdout/stderr와 exit code를 기록한다. 명령 변경은 `계획 대비 변경 사항`에 사유를 남긴다.

### API-1 중간 검증

명령:
`go test -count=1 ./packages/go/streamgate -run '^Test(FilterHoldRequirementValidatesModeMatrix|EvidencePlanComposesOnlyBlockingRequirements|EvidenceTail(RollingRuneThresholdAndLookBehind|PreservesKoreanRuneChunks|KeysFragmentsByToolCall))$'`

결과:
PASS — 5개 함수 18 subtest 통과 (0.002s)

### API-2 중간 검증

명령:
`go test -race -count=1 ./packages/go/streamgate -run '^TestEvidenceTail(ConfirmsOnlyReleasedPrefix|OverflowSignalsNoRelease|RecoveryTransitionsInvalidatePreparedRelease)$'`

결과:
PASS — 3개 함수 9 subtest 통과, race 없음 (0.002s)

### 호스트 Go 확인

명령:
`command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT`

결과:
`/config/.local/bin/go → /config/opt/go/bin/go, go1.26.2 linux/arm64, GOROOT=/config/opt/go` PASS

### 포맷

명령:
`gofmt -d packages/go/streamgate/evidence_tail.go packages/go/streamgate/evidence_tail_test.go`

결과:
stdout 없음 PASS

### Focused package

명령:
`go test -count=1 ./packages/go/streamgate -run '^Test(FilterHoldRequirement|EvidencePlan|EvidenceTail)'`

결과:
PASS — 8개 함수 33 subtests (0.002s)

### Package race

명령:
`go test -race -count=1 ./packages/go/streamgate`

결과:
PASS — 전체 패키지, race 없음 (1.835s)

### Vet

명령:
`go vet ./packages/go/streamgate`

결과:
PASS, stdout 없음

### Proto setup

명령:
`make proto`

결과:
성공, proto/gen/iop diff 없음

### Platform transport

명령:
`go test -count=1 ./apps/edge/internal/transport ./apps/node/internal/transport`

결과:
FAIL — host GOROOT mismatch (`crypto/internal/fips140cache is not in std`). 계획 expected failure. 재개 조건: host Go 설치에서 fips140cache 패키지 복구. 우회 toolchain 미사용.

### Diff hygiene

명령:
`git diff --check -- packages/go/streamgate proto/gen/iop`

결과:
stdout 없음 PASS

명령:
`git status --short -- proto/gen/iop`

결과:
stdout 없음 PASS

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## 섹션 소유권

| Section | Owner | Note |
|---------|-------|------|
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| Roadmap Targets | Fixed at stub creation from plan when present | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS |
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
| Agent UI Completion | Mixed | Present only for plan-required agent-ui code work; implementing agent fills actual evidence, review agent applies `구현됨` status/evidence update on PASS and copies the section into `complete.log` |
| 구현 항목별 완료 여부 (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| 구현 체크리스트 (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only; final checkbox is mandatory before saving |
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan |
| 검증 결과 (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `계획 대비 변경 사항` entry |
| 코드리뷰 결과 | Review agent appends | Not included in stub |

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail
  - completeness: Fail
  - test coverage: Fail
  - API contract: Fail
  - code quality: Pass
  - implementation deviation: Fail
  - verification trust: Fail
  - spec conformance: Fail
- 발견된 문제:
  - Required — `packages/go/streamgate/evidence_tail.go:864`: `PrepareRelease(epochID)`가 epoch을 조회·검증하지 않고 map iteration으로 임의의 pending channel을 선택하며, token도 channel만 기억한다. 그 결과 잘못된/stale epoch이 준비되고, prepare 뒤 append된 event 또는 다른 prepared token과 겹치는 prefix까지 `ConfirmRelease`가 commit할 수 있다. epoch→channel/snapshot을 고정한 one-shot prepared record를 저장하고 unknown/stale/duplicate/overlapping token과 prepared event 수를 넘는 confirm을 거부하며 multi-channel, post-prepare append, concurrent prepared-token 회귀 테스트를 추가한다.
  - Required — `packages/go/streamgate/evidence_tail.go:770`: fragment completion은 별도 `RegisterFragment` 호출에 의존하고, 같은 tool ID의 후속 fragment를 누적하지 않으며, 한 ID 완료 뒤 `PrepareRelease`가 channel 전체 pending을 반환해 아직 미완성인 다른 tool call까지 release할 수 있다. `Append`에서 channel+tool-call ID별 fragment와 bound를 일관되게 소유하고 완료 epoch/release snapshot을 그 ID의 safe prefix에만 결속한 뒤 interleaved partial-release/bound 회귀를 추가한다.
  - Required — `packages/go/streamgate/evidence_tail.go:389`: channel requirement 합성이 같은 mode의 threshold/bound 차이를 합성하지 않아 binding 순서에 따라 결과가 달라지고, public constructor로 `max_buffer_runes` override를 표현할 수 없으며 `SubscribeKinds`는 내부 slice를 그대로 노출한다. 또한 `Append`는 subscribed kind를 적용하지 않고 no-hold 경로에서 UTF-8 검증 전에 Ready를 반환하며 rolling threshold보다 작은 hard bound도 허용한다. SDD field matrix와 deterministic strongest composition, defensive copy, event applicability, fail-closed UTF-8, reachable threshold invariant를 구현하고 순서 반전/비구독 event/observe-only invalid UTF-8/bound matrix 테스트를 추가한다.
  - Required — `packages/go/streamgate/evidence_tail.go:949`: confirm된 look-behind를 effective `evidence_runes`가 아니라 `max_buffer_runes`로 trim하고, 마지막 event 하나가 bound보다 커도 그대로 보존한다. release cursor 상태도 구현돼 있지 않아 continuation에서 보존할 cursor가 없다. Unicode rune 경계에서 effective evidence window 이하로 정확히 자르고 committed cursor를 confirm된 prefix만큼 갱신·보존하며 replace/continuation과 oversized single-event 회귀를 추가한다.
  - Required — `agent-task/m-stream-evidence-gate-core/06+01_evidence_tail/WORK_LOG.md:83`: 완료 checkpoint 시각이 dispatcher 종료 시각보다 뒤이고 최신 실행의 종료 기록은 `exit_code: 1`이다(`WORK_LOG.md:130`). 현재 plan에 성공한 worker/selfcheck 실행 블록이 없으므로 완료·검증 증거를 신뢰할 수 없다. 후속 plan 실행에서 이전 블록을 수정하지 말고 새 실행 블록에 실제 순서의 checkpoint/검증/최종 리포트와 성공 종료 기록을 남긴다.
- 다음 단계: 현재 pair를 아카이브하고 isolated-reassessment로 생성한 후속 PLAN/CODE_REVIEW pair에서 Required 5건을 수정·재검증한다.
