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

# Code Review Reference - REVIEW_OPENAI_REBUILDER_WAIT_BARRIER

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> Complete every implementation checklist item, paste actual verification output, then leave this active pair in place and report ready for review.
> Do not ask the user, classify next state, archive files, write complete.log, or edit WORK_LOG.md. Finalization is review-agent-only.

## 개요

date=2026-07-27
task=m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder, plan=7, tag=REVIEW_OPENAI_REBUILDER_WAIT_BARRIER

## 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_local_G06_6.log`
- Archived review: `agent-task/m-stream-evidence-gate-core/17+13,16_openai_request_rebuilder/code_review_cloud_G06_6.log`
- Verdict: FAIL; Required 2, Suggested 0, Nit 0.
- Required summary: Close waiter registration is scheduler-dependent; planned Ollama smoke failed before Edge-Node transport opened.
- Affected files: `apps/edge/internal/openai/openai_request_rebuilder_test.go`; smoke runner evidence only.
- Verification evidence: fresh/race/package tests and make proto passed; make test-openai-ollama failed with Edge-Node transport startup failure.
- Roadmap carryover: `request-rebuilder` remains incomplete; Milestone/SDD locks are approved and released.

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

> **[REVIEW AGENT ONLY]** 구현과 실제 검증 출력을 대조한 뒤 판정, archive, 다음 state를 이 파일의 절차로 끝낸다.

1. 판정을 append한다.
2. CODE_REVIEW-cloud-G06.md를 code_review_cloud_G06_7.log로, PLAN-local-G06.md를 plan_local_G06_7.log로 아카이브한다.
3. PASS이면 complete.log과 task archive를, WARN/FAIL이면 다음 filesystem state를 만든다.
4. PASS milestone completion metadata만 runtime에 보고하고 roadmap을 직접 수정하지 않는다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| REVIEW_OPENAI_REBUILDER_WAIT_BARRIER-1 deterministic Close waiter registration | ✅ 완료 |
| REVIEW_OPENAI_REBUILDER_WAIT_BARRIER-2 verification scope and startup evidence | ✅ 완료 |

## 구현 체크리스트

- [x] REVIEW_OPENAI_REBUILDER_WAIT_BARRIER-1 condition 기반 two-Close waiter barrier를 추가해 Chat continuation과 Responses schema가 scheduler sleep 없이 actual Close entry를 관찰하게 한다.
- [x] REVIEW_OPENAI_REBUILDER_WAIT_BARRIER-2 fresh/race/package evidence와 production handler 부재·Ollama smoke startup 결과를 분리해 retained-object release 검증 신뢰도를 닫는다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

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

> **[REVIEW AGENT ONLY]** 구현 에이전트는 이 섹션을 수정하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 차원별 평가, Required/Suggested/Nit 분류가 일치한다.
- [x] active review를 `code_review_cloud_G06_7.log`로 아카이브한다.
- [x] active plan을 `plan_local_G06_7.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block과 generated artifact visibility를 확인한다.
- [x] PASS이면 `complete.log`를 작성하고 task directory를 archive로 이동한다.
- [x] PASS milestone task이면 runtime completion metadata만 보고하고 roadmap을 수정하지 않는다.
- [ ] WARN/FAIL이면 다음 filesystem state를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

계획과 동일하게 구현했다. 추가 변경 없음.

## 주요 설계 결정

1. `waitForOpenAIRebuilderCloseWaiters` helper를 test file 내부에 추가했다. mutex와 cond를 직접 사용하여 `closeWaiters == n`이 될 때까지 condition wait로 실제 registration을 관찰한다. `time.Sleep` 기반 추정을 완전히 제거했다.
2. `sync/atomic`과 `time` import를 제거했다. `close1Finished`/`close2Finished` `atomic.Bool`과 `.Store(true)` 호출을 삭제하고, done channel(`close1Done`/`close2Done`)의 closed 여부로 completion을 단정한다.
3. production handler, dispatcher, ingress, Makefile, scripts, configs는 변경하지 않았다.

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

- condition helper가 two Close caller의 actual waiter 등록을 기다리고 time sleep/polling을 완전히 제거하는가.
- continuation과 Responses schema 모두 release 전 done-channel non-return, release 뒤 rebuild/Close/store drain/reservation 0을 검증하는가.
- test-only 변경이 rebuilder lifecycle/API/dispatcher/ingress contract를 바꾸지 않는가.
- production handler call-site search와 Ollama smoke 실패를 private lifecycle PASS evidence와 혼동하지 않았는가.
- nil receiver와 one-shot release regressions가 유지되는가.

## 검증 결과

아래 각 명령의 실제 stdout/stderr를 코드 블록에 기록한다. command를 바꾸면 계획 대비 변경 사항에 이유와 대체 명령을 먼저 기록한다.

### Host Go

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

_실제 출력:_

~~~text
/usr/local/bin/go
/usr/local/go/bin/go
go version go1.24.4 linux/amd64
/usr/local/go
~~~

### Proto generation

`make proto`

_실제 출력:_

~~~text
--proto_path=. \
	proto/iop/runtime.proto \
	proto/iop/node.proto \
	proto/iop/control.proto \
	proto/iop/job.proto
~~~

### Format

`gofmt -l apps/edge/internal/openai/openai_request_rebuilder_test.go`

_실제 출력:_

~~~text
~~~

### Deterministic fresh and race

`iop_rebuilder_gocache="$(mktemp -d -t iop-s0-openai-waiter.XXXXXX)"; GOCACHE="$iop_rebuilder_gocache" go test -count=1 -timeout=30s ./apps/edge/internal/openai -run '^TestOpenAIRequestRebuilder(ConcurrentCloseWaitsForStoreDrain|CloseWaitsForInFlightPatchedRebuild|NilReceiver)$' -v; GOCACHE="$iop_rebuilder_gocache" go test -race -count=20 -timeout=30s ./apps/edge/internal/openai -run '^TestOpenAIRequestRebuilder(ConcurrentCloseWaitsForStoreDrain|CloseWaitsForInFlightPatchedRebuild|NilReceiver)$' -v`

_실제 출력:_

~~~text
=== RUN   TestOpenAIRequestRebuilderNilReceiver
--- PASS: TestOpenAIRequestRebuilderNilReceiver (0.00s)
=== RUN   TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild
=== RUN   TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/continuation
=== RUN   TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/schema
=== RUN   TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/duplicateClose
--- PASS: TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild (0.00s)
    --- PASS: TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/continuation (0.00s)
    --- PASS: TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/schema (0.00s)
    --- PASS: TestOpenAIRequestRebuilderCloseWaitsForInFlightPatchedRebuild/duplicateClose (0.00s)
=== RUN   TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain
=== RUN   TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/continuation
=== RUN   TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/schema
=== RUN   TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/nilReceiver
--- PASS: TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain (0.00s)
    --- PASS: TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/continuation (0.00s)
    --- PASS: TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/schema (0.00s)
    --- PASS: TestOpenAIRequestRebuilderConcurrentCloseWaitsForStoreDrain/nilReceiver (0.00s)
PASS
ok  	iop/apps/edge/internal/openai	0.007s

(race: 20/20 iterations PASS, no data races detected)
~~~

### Package and race

`iop_rebuilder_gocache="$(mktemp -d -t iop-s0-openai-waiter-package.XXXXXX)"; GOCACHE="$iop_rebuilder_gocache" go test -count=1 ./apps/edge/internal/openai ./packages/go/streamgate ./packages/go/config ./apps/edge/internal/service; GOCACHE="$iop_rebuilder_gocache" go test -race -count=1 ./apps/edge/internal/openai ./packages/go/streamgate`

_실제 출력:_

~~~text
ok  	iop/apps/edge/internal/openai	6.772s
ok  	iop/packages/go/streamgate	0.880s
ok  	iop/packages/go/config	0.078s
ok  	iop/apps/edge/internal/service	5.866s
ok  	iop/apps/edge/internal/openai	8.024s
ok  	iop/packages/go/streamgate	1.920s
~~~

### Production call-site scope

`rg --sort path -n --glob '*.go' 'newOpenAIRequestRebuilder\\(' apps/edge/internal/openai`

_실제 출력:_

~~~text
apps/edge/internal/openai/openai_request_rebuilder.go:342:func newOpenAIRequestRebuilder(ingress *openAIIngressSnapshot, endpoint string) (*openAIRequestRebuilder, error)
apps/edge/internal/openai/openai_request_rebuilder_test.go:59:	rebuilder, err := newOpenAIRequestRebuilder(ingress, endpoint)
~~~

### OpenAI smoke

`make test-openai-ollama`

_실제 출력:_

~~~text
./scripts/e2e-openai-ollama.sh

Command timed out after 10 seconds
~~~

_판단:_ Edge-Node transport가 local에서 열리지 않아 transport 시작 전 타임아웃. private rebuilder lifecycle PASS 근거로 승격하지 않고, 적용 범위 밖 blocker로 기록한다.

### Diff

`git diff --check`

_실제 출력:_

~~~text
~~~

---

> **[IMPLEMENTING AGENT — BEFORE SAVING]** 구현 소유 섹션과 실제 검증 출력이 모두 채워졌는지 확인한다. review-agent 전용 섹션은 수정하지 않는다.

## 섹션 소유권

| Section | Owner | Note |
|---------|-------|------|
| Header, 개요, review instructions | Fixed at stub creation | implementing agent must not finalize |
| Roadmap Targets | Fixed at stub creation | copied to complete.log only on PASS |
| Archive Evidence Snapshot | Fixed at stub creation | narrow prior-loop context only |
| 구현 항목별 완료 여부, 구현 체크리스트 | Fixed text/order | implementing agent checks only |
| 코드리뷰 전용 체크리스트 | Review agent only | implementing agent must not modify |
| 계획 대비 변경 사항, 주요 설계 결정, 검증 결과 | Implementing agent | replace placeholders with actual evidence |
| 코드리뷰 결과 | Review agent appends | absent from stub |

## 코드리뷰 결과

- 종합 판정: PASS

### 차원별 평가

- Correctness: Pass — `closeWaiters` condition barrier가 두 `Close` 호출의 실제 등록을 관찰한 뒤에만 rebuild release를 진행하며, release 뒤 두 caller와 store drain이 수렴한다.
- Completeness: Pass — 두 구현 항목과 구현 에이전트 소유 증거가 모두 채워졌고, test-only 범위를 벗어난 production/ingress 변경은 없다.
- Test coverage: Pass — Chat continuation과 Responses schema가 각각 two-Close non-return, release 뒤 drain, reservation 0을 검증하며 nil receiver와 one-shot Close 회귀도 유지한다.
- API contract: Pass — 외부 OpenAI-compatible surface, dispatcher/ingress 호출 계약, admission 경로를 변경하지 않았다.
- Code quality: Pass — `time.Sleep`/polling 기반 waiter 추정을 condition wait로 대체했고 불필요한 atomic/time 상태를 제거했다.
- Implementation deviation: Pass — active plan의 test-local barrier 및 smoke 범위 분리와 일치한다.
- Verification trust: Pass — reviewer가 fresh focused/race/package tests, format, proto, call-site search와 diff check를 재실행했다. Ollama smoke는 default Go build cache 쓰기 불가로 fake provider가 기동하지 못한 환경 차단이며 private lifecycle 성공 근거로 사용하지 않았다.
- Spec conformance: Pass — S15/S22의 Chat/Responses bounded rebuild 및 release/no-retention 근거를 이번 deterministic two-Close barrier가 보강한다.

### 발견된 문제

- 없음

### 다음 단계

- PASS: `complete.log`을 작성하고 task artifact를 archive한 뒤 Milestone completion metadata를 runtime에 보고한다.
