<!-- task=m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder plan=1 tag=REVIEW_OPENAI_REBUILDER -->

# Code Review Reference - REVIEW_OPENAI_REBUILDER

> **[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-26
task=m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder, plan=1, tag=REVIEW_OPENAI_REBUILDER

## 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:
  - `request-rebuilder`: endpoint별 bounded lossless rebuild와 host re-admission
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Prior task: `agent-task/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder`
- Archived plan: `agent-task/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder/plan_cloud_G09_0.log`
- Archived review: `agent-task/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder/code_review_cloud_G09_0.log`
- Verdict: FAIL
- Findings: Required 3, Suggested 0, Nit 0.
- Required summary: 실제 full-body 복사들이 retained/peak에서 누락됨; patch map이 상한 밖에서 복제되고 `Close`에서 해제되지 않음; OpenAI smoke와 실제 entrypoint full-cycle evidence가 없음.
- Affected files: `packages/go/streamgate/ingress_snapshot.go`, `apps/edge/internal/openai/{stream_gate_ingress.go,openai_request_rebuilder.go,provider_model_rewrite.go,input_estimator.go,chat_handler.go,responses_handler.go,provider_tunnel.go}` 및 대응 테스트.
- Verification evidence: fresh package tests와 race는 PASS했고 `git diff --check`도 PASS했지만, 해당 출력은 실제 backing 누락을 관찰하지 못했고 smoke/full-cycle은 실행되지 않았다.
- Roadmap carryover: `request-rebuilder`는 미완료이며 Milestone/SDD 잠금은 승인·해제 상태다.
- 구현에 더 자세한 prior context가 꼭 필요할 때만 위 두 archived log를 좁게 다시 읽는다.

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

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

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

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

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| REVIEW_OPENAI_REBUILDER-1 실제 backing과 ledger 일치 | [x] |
| REVIEW_OPENAI_REBUILDER-2 bounded one-shot patch lifecycle | [x] |
| REVIEW_OPENAI_REBUILDER-3 통합 검증 신뢰도 복구 | [x] |

## 구현 체크리스트

- [x] REVIEW_OPENAI_REBUILDER-1 Core owned backing/commit과 OpenAI canonical/rebuilt dispatch lease를 추가해 실제 live backing과 retained/peak를 일치시킨다.
- [x] REVIEW_OPENAI_REBUILDER-2 continuation/schema patch를 동일 상한에 one-shot 예약하고 duplicate/overflow/close/cancel에서 즉시 해제한다.
- [x] REVIEW_OPENAI_REBUILDER-3 near-limit/release 회귀, fresh unit/race, OpenAI smoke와 실제 entrypoint full-cycle evidence를 완성한다.
- [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_cloud_G10_1.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G10_1.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/17+13,16_openai_request_rebuilder/`를 `agent-task/archive/YYYY/MM/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder/`로 이동하고 최종 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`를 작성하지 않는다.

## 계획 대비 변경 사항

- 계획의 production/test 범위와 공개 계약은 그대로 구현했다.
- `json.RawMessage` semantic view가 canonical과 같은 backing일 때 `json.Marshal`로 동일 full-body를 잠시 복제하지 않도록, validated raw alias를 직접 ownership-transfer하는 최적화를 함께 적용했다. 이는 REVIEW_OPENAI_REBUILDER-1의 실제 backing 일치 조건을 만족하기 위한 범위 내 보강이다.
- 실제 entrypoint 검증은 기본 config를 수정하지 않고 `/tmp/iop-g10-full-cycle.C75Cpy`의 임시 config/FIFO/deterministic persistent `fake-cli` harness로 수행했다. 첫 harness 실행은 Node의 multiline payload 중 첫 줄만 `[node-message]` prefix를 갖는 출력 형식을 extractor가 잘못 해석해 validator만 실패했다. 실제 Edge/Node 원문은 정상 순서였으며, multiline-aware extractor로 전체 cycle을 새로 실행해 exit 0과 payload equality를 확인했다.
- 실행 중 병렬 선행 task가 `packages/go/streamgate/runtime.go`를 작성하던 순간 REVIEW_OPENAI_REBUILDER-2 명령이 compile 실패했으나, 해당 범위에 손대지 않고 선행 작업 종료 뒤 같은 명령을 fresh 재실행해 통과했다. 아래에는 최종 안정 상태의 원문 출력을 기록한다.

## 주요 설계 결정

- 기존 defensive-copy `IssueBackingHandle`/`CommitTyped`/accessor는 호환 유지하고, opt-in `IssueOwnedBackingHandle`/`CommitOwnedTyped`와 lifetime-bound read-only alias accessor만 추가했다.
- OpenAI canonical, exact replay, rebuilt output은 각각 하나의 owned backing만 보존한다. `openAIRebuiltLease`가 synchronous provider submission 동안 exact 또는 rebuilt body alias와 snapshot/guard를 붙잡고, submission 반환 직후 exactly-once release한다.
- byte token estimator는 `[]byte`에서 UTF-8 rune을 직접 세어 기존 string estimator와 invalid UTF-8까지 동일한 결과를 내면서 full-body string 변환을 제거한다.
- continuation/schema patch는 ingress의 같은 rebuild reservation ledger에 넣고 duplicate를 거부하며, directive take 시 map에서 제거하는 one-shot 소유권으로 처리한다. success/error/context cancel/Close에서 guard와 slice를 정확히 한 번 해제하고, output reservation은 살아 있는 patch reservation을 포함한 current peak를 검사한다.
- exact owned peak와 peak-1 overflow fixture가 canonical + patch + output 실제 backing 합계를 직접 검증하고, overflow에서는 patch/rebuilt lease/reservation이 모두 0으로 수렴하는지 확인한다.

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

- Core copy API 호환은 유지하면서 owned transfer만 opt-in이고 backing identity/immutability/release 테스트가 있는가.
- exact canonical, patch backing, single rebuild output, provider dispatch body의 실제 live ownership이 draft retained/peak와 일치하는가.
- patch가 duplicate/oversize/take/error/cancel/close에서 zero dispatch와 exactly-once release로 수렴하는가.
- Chat/Responses unknown byte ranges, auth 비보존, actual admission/path switch가 유지되는가.
- package/race뿐 아니라 OpenAI smoke와 실제 dev entrypoint cycle의 원문 evidence가 있는가.

## 검증 결과

아래 각 명령의 실제 stdout/stderr를 코드 블록에 기록한다. 명령을 바꾸면 `계획 대비 변경 사항`에 대체 명령과 이유를 먼저 적는다. 긴 출력은 repo 밖 저장 경로와 저장 명령을 기록한다. blocker는 성공으로 바꾸지 않는다.

### Host Go

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

_실제 출력:_

```text
/config/.local/bin/go
/config/opt/go/bin/go
go version go1.26.2 linux/arm64
/config/opt/go
```

### REVIEW_OPENAI_REBUILDER-1 중간 검증

`gofmt -w packages/go/streamgate/ingress_snapshot.go packages/go/streamgate/ingress_snapshot_test.go apps/edge/internal/openai/stream_gate_ingress.go apps/edge/internal/openai/openai_request_rebuilder.go apps/edge/internal/openai/provider_model_rewrite.go apps/edge/internal/openai/input_estimator.go apps/edge/internal/openai/input_estimator_test.go apps/edge/internal/openai/chat_handler.go apps/edge/internal/openai/responses_handler.go apps/edge/internal/openai/provider_tunnel.go && go test -count=1 ./packages/go/streamgate ./apps/edge/internal/openai`

_실제 출력:_

```text
ok  	iop/packages/go/streamgate	0.878s
ok  	iop/apps/edge/internal/openai	6.768s
```

### REVIEW_OPENAI_REBUILDER-2 중간 검증

`go test -count=1 ./apps/edge/internal/openai -run '^TestOpenAI(RequestRebuilder|Ingress|Provider)' && go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai`

_실제 출력:_

```text
ok  	iop/apps/edge/internal/openai	0.021s
ok  	iop/packages/go/streamgate	1.929s
ok  	iop/apps/edge/internal/openai	8.103s
```

### REVIEW_OPENAI_REBUILDER-3 중간 OpenAI smoke

`make test-openai-ollama`

_실제 출력:_

```text
./scripts/e2e-openai-ollama.sh
[openai-ollama] OpenAI-compatible Ollama serving test PASSED.
```

### 최종 format

`gofmt -l packages/go/streamgate/ingress_snapshot.go packages/go/streamgate/ingress_snapshot_test.go apps/edge/internal/openai/stream_gate_ingress.go apps/edge/internal/openai/openai_request_rebuilder.go apps/edge/internal/openai/openai_request_rebuilder_test.go apps/edge/internal/openai/provider_model_rewrite.go apps/edge/internal/openai/input_estimator.go apps/edge/internal/openai/input_estimator_test.go apps/edge/internal/openai/chat_handler.go apps/edge/internal/openai/responses_handler.go apps/edge/internal/openai/provider_tunnel.go`

_실제 출력:_

```text
(출력 없음, exit 0)
```

### 최종 fresh unit

`go test -count=1 ./packages/go/streamgate ./packages/go/config ./apps/edge/internal/openai ./apps/edge/internal/service`

_실제 출력:_

```text
ok  	iop/packages/go/streamgate	0.870s
ok  	iop/packages/go/config	0.058s
ok  	iop/apps/edge/internal/openai	6.755s
ok  	iop/apps/edge/internal/service	5.863s
```

### 최종 race

`go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai`

_실제 출력:_

```text
ok  	iop/packages/go/streamgate	2.918s
ok  	iop/apps/edge/internal/openai	8.002s
```

### 미계상 copy search

`if rg --sort path -n 'estimateInputTokens\(string\((body|canonicalBody|output)\)\)|Accessor\(\)\.(Canonical|TypedView)\(' apps/edge/internal/openai/openai_request_rebuilder.go apps/edge/internal/openai/provider_model_rewrite.go apps/edge/internal/openai/responses_handler.go; then exit 1; fi`

_실제 출력:_

```text
(출력 없음, exit 0)
```

### 최종 OpenAI smoke

`make test-openai-ollama`

_실제 출력:_

```text
./scripts/e2e-openai-ollama.sh
[openai-ollama] OpenAI-compatible Ollama serving test PASSED.
```

### 실제 entrypoint full-cycle

별도 프로세스로 `./scripts/dev/edge.sh`와 `./scripts/dev/node.sh`를 실행하고 Edge console에서 `/nodes`, 같은 session 메시지 2회, `/capabilities`, `/transport`, `/sessions`를 순서대로 입력한다.

_실제 명령·stdout/stderr 또는 blocker와 재개 조건:_

```text
$ cycle_dir=$(mktemp -d /tmp/iop-g10-full-cycle.XXXXXX)
$ IOP_EDGE_CONFIG="$cycle_dir/edge.yaml" ./scripts/dev/edge.sh < "$cycle_dir/edge.fifo" > "$cycle_dir/edge.out" 2>&1 &
$ IOP_NODE_CONFIG="$cycle_dir/node.yaml" ./scripts/dev/node.sh > "$cycle_dir/node.out" 2>&1 &
$ printf '%s\n' '/nodes' 'Return token IOP_G10_ALPHA' 'Return token IOP_G10_BETA' '/capabilities' '/transport' '/sessions' '/exit' >&3
$ diff -u "$cycle_dir/node.payloads" "$cycle_dir/edge.payloads"
$ awk '<각 run에서 start 뒤 MSG 2개, 그 뒤 complete 1개, late MSG 없음 검증>' "$cycle_dir/edge.out"
FULL_CYCLE_LOG_DIR=/tmp/iop-g10-full-cycle.C75Cpy
=== EDGE TRANSCRIPT ===
[edge] config=/tmp/iop-g10-full-cycle.C75Cpy/edge.yaml
  node0 = test-node (test-node)
[node0-evt] start run_id=manual-1785067395671455880
[node0-msg] IOP_G10_ALPHA
[node0-msg] IOP_G10_ALPHA_TAIL
[node0-evt] complete run_id=manual-1785067395671455880 detail="idle-timeout"
[node0-evt] start run_id=manual-1785067396892881339
[node0-msg] IOP_G10_BETA
[node0-msg] IOP_G10_BETA_TAIL
[node0-evt] complete run_id=manual-1785067396892881339 detail="idle-timeout"
  adapter = cli
  targets = fake-cli
  adapter = cli
  connected = true
  node_id = test-node
  session_id = default
  state = connected
  target = fake-cli
sessions: 1
  [0] mode=persistent target=fake-cli session=default
=== NODE PAYLOADS ===
IOP_G10_ALPHA
IOP_G10_ALPHA_TAIL
IOP_G10_BETA
IOP_G10_BETA_TAIL
FULL_CYCLE_PASS node payloads equal edge payloads; each complete follows exactly two messages
```

### Diff

`git diff --check`

_실제 출력:_

```text
(출력 없음, exit 0)
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
> 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 |
| 코드리뷰 전용 체크리스트 | 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: Pass
  - Spec conformance: Fail
- 발견된 문제:
  - Required: `apps/edge/internal/openai/openai_request_rebuilder.go:271`의 rebuilt store는 폐쇄 상태를 보존하지 않고, `openAIRebuiltRequestStore.close`(`:301`)가 map만 교체하므로 `openAIRequestRebuilder.Close`(`:340`) 뒤 exact `RebuildRequest`가 `put`(`:280`)으로 새 lease를 다시 저장한다. SDD S22와 계획의 request termination release 조건에 어긋난다. 깨끗한 HEAD에서 `Close()` 후 exact rebuild를 호출하는 집중 회귀 테스트는 `RebuildRequest succeeded after rebuilder Close`로 실패했다. rebuilt store/재빌더 종료를 terminal state로 선형화해 폐쇄 뒤 `put`과 rebuild를 `streamgate.ErrIngressSnapshotClosed`로 거부하고 전달된 lease를 해제하며, sequential close-after-rebuild와 close-vs-put/rebuild race에서 lease·guard·reservation이 남지 않는 회귀 테스트를 추가한다.
- 다음 단계:
  - plan skill의 WARN/FAIL follow-up으로 terminal Close 경계와 회귀/race 검증을 보완한다.
