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

# Code Review Reference - 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=0, tag=OPENAI_REBUILDER

## Roadmap Targets

- Milestone: `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md`
- Task ids: `request-rebuilder`
- Completion mode: check-on-pass

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

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

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

1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G09.md` → `code_review_cloud_G09_0.log`, `PLAN-cloud-G09.md` → `plan_cloud_G09_0.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` 위치에서 체크한 뒤 보고한다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| REBUILD-1 bounded ingress | [x] |
| REBUILD-2 endpoint rebuilder | [x] |
| REBUILD-3 dispatcher adapter | [x] |
| REBUILD-4 fixtures/contracts | [x] |
| REBUILD-5 회귀 | [x] |

## 구현 체크리스트

- [x] REBUILD-1 Chat/Responses pre-read limit+1 gate와 request-local snapshot lifecycle을 적용한다.
- [x] REBUILD-2 exact/continuation/schema OpenAI JSON rebuilder와 retained peak 검사를 구현한다.
- [x] REBUILD-3 기존 admission을 감싼 AttemptDispatcher/Binding/Controller adapter를 구현한다.
- [x] REBUILD-4 unknown field/auth 비보존/path switch/overflow/no-dispatch/release fixtures를 추가한다.
- [x] REBUILD-5 config/streamgate/OpenAI/service 회귀와 diff 검증을 수행한다.
- [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_G09_0.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G09_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/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`를 작성하지 않는다.

## 계획 대비 변경 사항

- 최상위 JSON byte-span 스캐너를 재빌더와 provider model/policy rewrite가 함께 쓰도록 `json_field_patch.go`로 분리했다. 계획의 single-output/비대상 byte 보존 원칙을 중복 없이 적용하기 위한 내부 구조 변경이다.
- `server.go`의 `runService` 인터페이스 자체는 바꾸지 않았다. 새 dispatcher가 기존 인터페이스의 `SubmitRun`/`SubmitProviderTunnel`/`SubmitProviderPool`/`CancelRun`을 그대로 소비하며, task 20이 제공할 codec event-source factory와 admission builder를 생성자 seam으로 받는다.
- focused tests 외에 기존 `dispatch_context_test.go`의 raw body fixture를 snapshot-backed fixture로 갱신했다. naked `rawBody` 제거에 따른 필수 회귀 보정이다.

## 주요 설계 결정

- HTTP body는 `MaxBytesReader`가 limit+1 probe를 수행한 뒤 Core builder에 canonical/typed backing으로 이전한다. canonical과 typed bytes가 같으면 한 backing handle을 공유하며 handler defer가 snapshot을 idempotent release한다.
- exact는 canonical bytes를 그대로 lease하고, continuation/schema는 Chat `messages` 또는 Responses `input` value span만 교체한다. model/policy rewrite도 같은 span patch와 Core rebuild guard를 사용하며 persistent request `map[string]json.RawMessage` tree를 만들지 않는다.
- rebuilt body는 request-local opaque ref store에만 남고 Core draft에는 ref/endpoint/family/token/retained·peak·max만 전달된다. overflow는 dispatchable lease를 만들기 전에 종료된다.
- dispatcher는 rebuilt lease를 한 번 인수하고 fresh admission builder가 만든 세 기존 surface 중 정확히 하나만 호출한다. pool의 normalized/tunnel 경로는 실제 `ProviderPoolDispatchResult.Path`로 정하고, binding model/provider/path는 실제 `RunDispatch`에서만 계산한다.
- provider auth callback은 admission에만 존재하고 tunnel dispatch 또는 pool `PrepareTunnel` 시점마다 실행된다. snapshot/rebuilder에는 auth header나 credential을 저장하지 않는다.
- controller는 현재 transport, rebuilt lease, `CancelRun`만 소유한다. abort는 한 번 cancel/close/release하고 이후 호출은 no-op이다. admission 뒤 binding/event-source 생성이 실패해도 동일 controller 경로로 transport를 취소·해제한다.

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

- body read 전에 상한이 적용되고 typed-view/rebuild overflow에서 dispatch 0인가.
- exact byte identity와 patched 비대상 byte-range 보존이 지켜지고 persistent RawMessage tree 없이 canonical full copy가 하나뿐인가.
- auth는 snapshot에 없고 dispatcher가 provider/model/path를 다시 결정하는가.
- release/cancel/normalized↔tunnel switch가 ownership leak 없이 수렴하는가.

## 검증 결과

### 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
```

### Unit/race

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

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

_실제 출력:_

```text
ok  iop/packages/go/streamgate          0.887s
ok  iop/packages/go/config              0.097s
ok  iop/apps/edge/internal/openai       6.776s
ok  iop/apps/edge/internal/service      5.865s

ok  iop/packages/go/streamgate          1.917s
ok  iop/apps/edge/internal/openai       8.056s
```

### 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
- 차원별 평가:
  - 정확성: Fail
  - 완전성: Fail
  - 테스트 커버리지: Fail
  - API 계약: Fail
  - 코드 품질: Pass
  - 계획 대비 변경: Fail
  - 검증 신뢰도: Fail
  - 스펙 정합성: Fail
- 발견된 문제:
  - Required — `apps/edge/internal/openai/openai_request_rebuilder.go:272`, `apps/edge/internal/openai/openai_request_rebuilder.go:295`, `apps/edge/internal/openai/openai_request_rebuilder.go:304`, `apps/edge/internal/openai/openai_request_rebuilder.go:123`, `apps/edge/internal/openai/provider_model_rewrite.go:206`, `apps/edge/internal/openai/provider_model_rewrite.go:222`, `apps/edge/internal/openai/provider_model_rewrite.go:227`, `apps/edge/internal/openai/responses_handler.go:287`: exact/rebuild/model rewrite/provider-pool 경로가 canonical/typed accessor의 방어 복사, patch output, `CommitTyped`의 추가 복사, dispatch body 복사를 동시에 소유하지만 retained/peak에는 snapshot backing만 보고한다. Core accessor와 commit이 실제로 복사하는 것은 `packages/go/streamgate/ingress_snapshot.go:534`, `packages/go/streamgate/ingress_snapshot.go:798`, `packages/go/streamgate/ingress_snapshot.go:817`에서 확인된다. 따라서 limit 부근 요청이 SDD의 “canonical full copy 하나”, “request가 소유한 backing의 보수적 합”, “rebuild 할당 전후 current peak” 조건(`agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md:83`, `agent-roadmap/sdd/knowledge-tool-optimization-extension/stream-evidence-gate-core/SDD.md:87`, S15/S22)을 어긴 채 통과할 수 있다. exact는 canonical backing lease를 재사용하고 rebuild는 단일 output의 소유권을 guard/snapshot으로 이전하거나, 불가피한 모든 복사를 pre/post peak에 명시적으로 계상하는 API로 바꿔야 한다. provider rewrite와 pool raw-body 소비도 같은 lease 경로를 사용하게 하고, limit 근처에서 실제 live backing/lease 수와 release를 검증하는 회귀 테스트를 추가한다.
  - Required — `apps/edge/internal/openai/openai_request_rebuilder.go:27`, `apps/edge/internal/openai/openai_request_rebuilder.go:48`, `apps/edge/internal/openai/openai_request_rebuilder.go:69`, `apps/edge/internal/openai/openai_request_rebuilder.go:90`, `apps/edge/internal/openai/openai_request_rebuilder.go:102`, `apps/edge/internal/openai/openai_request_rebuilder.go:112`, `apps/edge/internal/openai/openai_request_rebuilder.go:219`: continuation/schema patch 저장소는 임의 크기 payload를 별도 map에 복사하고 조회 때 다시 복사하지만 snapshot 상한과 retained/peak ledger에 포함되지 않으며, `Close`도 rebuilt lease만 닫고 patch map을 비우지 않는다. 이는 S22의 request-local owned backing 합산과 종료/cancel/overflow release 조건을 위반한다. patch backing을 동일 request 상한 아래에서 ledger/lease로 소유하고 one-shot 조회 또는 명시적 ownership transfer로 중복 복사를 없애며, 모든 종료 경로에서 저장소를 비우고 oversized patch zero-dispatch 및 close/cancel release 회귀 테스트를 추가한다.
  - Required — `agent-task/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder/CODE_REVIEW-cloud-G09.md:123`: 구현 증거는 package unit/race와 diff 검사뿐이다. 이 변경은 OpenAI route, provider tunnel/auth/admission이라는 사용자 실행 파이프라인을 바꾸므로 `agent-ops/rules/project/domain/testing/rules.md:62`, `agent-ops/rules/project/domain/testing/rules.md:86`, `agent-ops/rules/project/domain/testing/rules.md:147`에 따라 관련 OpenAI smoke와 실제 entrypoint full-cycle evidence가 필수다. 수정 후 `make test-openai-ollama`를 실행하고, `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 별도 프로세스로 실행한 실제 OpenAI/Edge-Node cycle 또는 정확한 환경 blocker·재개 조건을 구현 증거에 기록해야 한다.
- 다음 단계: Required 3건을 반영하는 후속 PLAN/CODE_REVIEW pair를 생성한다.
