<!-- task=m-iop-hot-path-one-shot-execution/15+13_chat_gate plan=1 tag=API milestone-task=terminal-control,chat-gate -->

# OpenAI Chat caller codec integration

## For the Implementing Agent

구현 후 `CODE_REVIEW-cloud-G10.md`의 구현 담당 섹션에 실제 변경·검증 출력을 채우고 active 파일을 유지한다. 차단 시 정확한 blocker와 재개 조건만 기록하며 archive/`complete.log` 작성이나 상태 판정은 하지 않는다.

## Background

이 child는 child 13의 normalized outer-turn events를 OpenAI Chat Completions caller wire로 encode한다. 선택된 provider protocol decode는 common predecessor 책임이며 `normalized_sse.go`에 provider-specific decoder를 복제하지 않는다.

## Archive Evidence Snapshot

- 이전 active plan/review pair는 구현 전에 source reanalysis로 대체됐다. 구현 evidence와 verdict는 없다.

## Analysis

### Files Read

- `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-hot-path-one-shot-execution/SDD.md`
- `agent-contract/outer/openai-compatible-api.md`
- `apps/edge/internal/openai/chat_handler.go`
- `apps/edge/internal/openai/normalized_sse.go`
- `apps/edge/internal/openai/hot_path_dispatch.go`
- `apps/edge/internal/openai/chat_stream_session_test.go`
- `agent-test/local/rules.md`

### SDD Criteria

- 승인 SDD S10/S12: one Chat response/SSE envelope, ordered content/reasoning/tool deltas, stable tool ids/indexes, aggregate usage, native finish/error semantics.
- caller `max_tokens`/`max_completion_tokens` 중 유효한 public cap을 outer turn에 적용한다.

### Verification Context

- deterministic handler/wire fixtures와 fresh race tests로 닫는다. 실제 Pi smoke는 child 21이다.

### Test Coverage Gaps

- preset branch의 already-dispatched initial result, multi-stage single stream, mixed-provider decode, output-cap/usage aggregation evidence가 없다.

### Symbol References

- public rename/remove 없음. 기존 ordinary Chat session behavior를 보존한다.

### Split Judgment

- stable contract: normalized outer events → Chat caller wire. Anthropic caller wire는 sibling 14, exhaustive errors는 child 17이다.

### Scope Rationale

- provider decoding, common sequencer, `/v1/responses`, observation, actual smoke는 제외한다.

### Final Routing

- evaluation_mode=isolated-reassessment, finalizer=`finalize-task-policy.sh pair`.
- build scores=2/2/2/1/2, risks=`temporal_state,boundary_contract,structured_interpretation,variant_product`(4), grade-boundary → `PLAN-cloud-G09.md`.
- review → `CODE_REVIEW-cloud-G10.md`; `large_indivisible_context=false`, recovery=0/false.

## Implementation Checklist

- [ ] [API-1] Add a caller-facing Chat outer codec and pass the already-dispatched preset result, stream mode, model, and caller output cap into the shared turn.
- [ ] [API-2] Add streaming/non-streaming, mixed-provider, fragmentation, tool, cap, usage, and baseline error handler fixtures.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Native Chat outer codec

**Problem:** the preset handler currently completes selector collection before `dispatchPresetTurn`, and direct writers produce a completed response rather than progressive caller chunks.

**Solution:** Create a Chat outer codec before consuming the existing initial dispatch result and call the shared runner without redispatch. Encode normalized content/reasoning/tool fragments into one Chat response identity with stable choice/tool indexes and one final finish/usage sequence. Resolve the public cap from `max_completion_tokens`/`max_tokens` and pass it to the outer sequencer. Support stream SSE and current non-stream JSON compatibility. Keep common hooks for child 17 pre/post-commit error mapping.

**Modified Files and Checklist:**

- [ ] Modify `apps/edge/internal/openai/chat_handler.go` to create the caller codec and pass initial dispatch/correlation/output policy into the shared turn.
- [ ] Modify `apps/edge/internal/openai/normalized_sse.go` only for normalized outer-event Chat encoding and stream/non-stream terminal rendering.

**Test Strategy:** handler fixtures use OpenAI and Anthropic provider-stage inputs but assert the same Chat caller protocol.

**Verification:** targeted API-2 command exits 0.

### [API-2] Chat wire evidence

**Problem:** ordinary Chat session tests do not cover multi-stage Hot Path composition.

**Solution:** Add fragmented direct/light/tool rows, mixed provider protocols, one response id/start, monotonic tool indexes, argument assembly, usage sum, length stop on cap, non-stream regression, and representative pre/post-commit errors. Leave the exhaustive terminal matrix to child 17.

**Modified Files and Checklist:**

- [ ] Add `apps/edge/internal/openai/hot_path_chat_gate_test.go` with handler-level response/SSE fixtures.
- [ ] Record actual output in `agent-task/m-iop-hot-path-one-shot-execution/15+13_chat_gate/CODE_REVIEW-cloud-G10.md`.

**Test Strategy:** parse chunks/JSON structurally and compare exact ids, indexes, finish reason, usage, and `[DONE]` placement.

**Verification:** run Final Verification; all commands exit 0 without race.

## Dependencies and Execution Order

1. Directory dependency `13` must produce `agent-task/m-iop-hot-path-one-shot-execution/13+12_outer_turn_integration/complete.log`.
2. Implement API-1, then API-2.

## Modified Files Summary

| File | Item |
|---|---|
| `apps/edge/internal/openai/chat_handler.go` | API-1 |
| `apps/edge/internal/openai/normalized_sse.go` | API-1 |
| `apps/edge/internal/openai/hot_path_chat_gate_test.go` | API-2 |
| `agent-task/m-iop-hot-path-one-shot-execution/15+13_chat_gate/CODE_REVIEW-cloud-G10.md` | API-2 |

## Final Verification

```bash
go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPathChat|TestChatStreamSession'
go test -race -count=1 ./packages/go/streamgate ./packages/go/config ./apps/edge/internal/openai ./apps/edge/internal/service
git diff --check
```

Expected: exit 0, provider-independent native Chat output, one response lifecycle, stable tool/cap/usage semantics, non-stream regression preserved.

After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
