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

# Code Review Reference - REVIEW_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 `Implementation Checklist`; 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 (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## Overview

date=2026-08-03
task=m-iop-hot-path-one-shot-execution/15+13_chat_gate, plan=2, tag=REVIEW_API

## Archive Evidence Snapshot

- The failed predecessor pair is `plan_cloud_G09_1.log` and `code_review_cloud_G10_1.log` in this task directory.
- Its verdict is `FAIL` with two Required findings: Light-stage output was buffered until terminal, and public Chat identity exposed logical request/normalized run IDs.
- Fresh predecessor verification passed targeted/common race tests, Edge vet, formatting, and diff checks; `review_rework_count=1` and `evidence_integrity_failure=false`.
- The follow-up must preserve selector classification before commit, progressively release only already-classified Light stages, and bind public identity only from provider-owned evidence.

## For the Review Agent

> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section.

Compare implementation of each item against source files and verify that output in `Verification Results` matches code.
Review completion means the following steps are finished:

1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals.
2. Archive `CODE_REVIEW-{review_lane}-{review_grade}.md` → `code_review_{review_lane}_{review_grade}_{review_log_number}.log` and `PLAN-{build_lane}-{build_grade}.md` → `plan_{build_lane}_{build_grade}_{plan_log_number}.log`.
3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/{task_name}/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill.
4. If PASS and task group is `m-<milestone-slug>`, preserve the first-line `milestone-task` metadata in `complete.log` and report it for the runtime aggregation event. Roadmap state evaluation belongs to `sync-milestone-workstate`.
5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting.

---

## Implementation Item Completion

| Item | Status |
|------|---------|
| REVIEW_API-1 Provider identity provenance | [x] |
| REVIEW_API-2 Progressive Chat release after classification | [x] |
| REVIEW_API-3 Regression and verification evidence | [x] |

## Implementation Checklist

- [x] [REVIEW_API-1] Preserve one stable provider Chat response ID across normalized RuntimeEvents and fail closed on missing or conflicting identity without substituting `RunId`.
- [x] [REVIEW_API-2] Wire already-classified streaming Light stages through live Core sources and flush each safe Chat delta immediately while holding one outer terminal.
- [x] [REVIEW_API-3] Add Node and Edge regressions for early flush, single public identity, normalized identity propagation, and logical/run-ID non-exposure.
- [x] Fill every implementation-owned section in `CODE_REVIEW-cloud-G10.md` with actual changes and fresh command output, then leave both active files in place for review.

## Review-Only Checklist

> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent.
> Implementing agents must not modify or check this section.

- [x] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`.
- [x] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match.
- [x] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G10_2.log`.
- [x] Archive active `PLAN-*-G??.md` to `plan_cloud_G10_2.log`.
- [x] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`.
- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
- [ ] If PASS, move active task directory `agent-task/{task_name}/` to `agent-task/archive/YYYY/MM/{task_name}/` and update this checklist at the final archive path.
- [ ] If PASS and task group is `m-<milestone-slug>`, preserve and report `milestone-task` metadata for runtime aggregation, without modifying roadmap or directly calling `update-roadmap`.
- [ ] If PASS for split work, remove empty active parent `agent-task/{task_group}/` or verify it was kept due to remaining siblings/files.
- [x] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.

## Deviations from Plan

- There are no behavioral deviations from the plan.
- The new mandatory provider identity made existing successful adapter and stage-source fixtures incomplete. Fixture-only updates were therefore also made in `apps/node/internal/adapters/openai_compat/thinking_policy_test.go`, `apps/node/internal/adapters/openai_compat/protocol_profile_test.go`, and `apps/edge/internal/openai/hot_path_terminal_control_test.go` so those fixtures carry an explicit provider response ID.
- The child-21 Pi smoke was not run or claimed because it is outside this task's ownership.

## Key Design Decisions

- The Node OpenAI-compatible adapter binds the first non-empty upstream SSE chunk `id`, attaches it as `RunEvent.metadata["openai_response_id"]` to every visible delta and the complete event, and rejects missing or conflicting identity. The Edge normalized path consumes only that metadata and never substitutes a run, logical-request, stage, node, or timestamp identity.
- The initial selector remains collected through terminal and structural classification. Only an already-classified streaming OpenAI Light stage selects the live normalized/tunnel source and runs through the existing Core stage runtime.
- A Light outer turn starts without a Chat response ID. Its first safe stage delta binds the first provider identity once; later stage identities remain stage correlation and usage keys without replacing the public outer ID.
- The request-local outer allocates final caller tool IDs before live tool release. The Chat callback writes and flushes role, reasoning, content, and tool fragments in release order, while the final writer alone owns finish, aggregate usage, and one `[DONE]` marker.
- The normalized live source projects complete-event native tool metadata into Core tool-fragment events ahead of the held Core terminal, preserving the same behavior available from incremental provider-tunnel decoding.
- Non-stream collectors, caller output caps, initial Direct rendering, and the Anthropic caller codec contract remain unchanged.

## Reviewer Checkpoints

- Confirm initial selector evidence remains fully collected and structurally classified before any caller commitment; only already-classified streaming Light stages release progressively.
- Confirm `openai_response_id` originates from the provider Chat SSE `id`, remains stable across normalized RuntimeEvents, and is never synthesized from a logical request, run, stage, node, or frame identity.
- Confirm the first visible stage binds one public outer Chat ID before the role/first delta, later stages do not replace it, and missing/conflicting identity fails closed.
- Confirm content, reasoning, and tool fragments flush before the provider stage terminal while finish, aggregate usage, and `[DONE]` are emitted exactly once at the outer terminal.
- Confirm the implementation reuses `hotPathNormalizedStageSource`, `hotPathTunnelStageSource`, and `runHotPathStage` rather than adding another provider decoder or bypassing Core.
- Confirm non-stream behavior, caller output caps, tool remapping, provider usage aggregation, and ordinary Chat behavior remain covered.
- Confirm no protobuf field, `/v1/responses`, Anthropic caller codec, roadmap state, or child-21 smoke ownership was added.

## Verification Results

### Node normalized identity

Command: `go test -race -count=1 ./apps/node/internal/adapters/openai_compat -run 'TestOpenAICompatExecute'`

```text
ok  	iop/apps/node/internal/adapters/openai_compat	1.109s
```

Exit status: 0

### Edge targeted behavior

Command: `go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPathChat|TestHotPathDirect|TestHotPathOuterTurn|TestChatStreamSession'`

```text
ok  	iop/apps/edge/internal/openai	2.142s
```

Exit status: 0

### Common race regression

Command: `go test -race -count=1 ./packages/go/streamgate ./packages/go/config ./apps/node/internal/adapters/openai_compat ./apps/edge/internal/openai ./apps/edge/internal/service`

```text
ok  	iop/packages/go/streamgate	2.092s
ok  	iop/packages/go/config	2.025s
ok  	iop/apps/node/internal/adapters/openai_compat	1.363s
ok  	iop/apps/edge/internal/openai	14.644s
ok  	iop/apps/edge/internal/service	7.189s
```

Exit status: 0

### Vet

Command: `go vet ./apps/node/internal/adapters/openai_compat ./apps/edge/...`

```text
```

Exit status: 0

### Formatting

Command: `gofmt -l apps/node/internal/adapters/openai_compat/stream.go apps/node/internal/adapters/openai_compat/request.go apps/node/internal/adapters/openai_compat/execute_test.go apps/edge/internal/openai/stream_gate_runtime.go apps/edge/internal/openai/hot_path_stage_stream.go apps/edge/internal/openai/hot_path_dispatch.go apps/edge/internal/openai/hot_path_terminal_control.go apps/edge/internal/openai/hot_path_light.go apps/edge/internal/openai/normalized_sse.go apps/edge/internal/openai/hot_path_chat_gate_test.go apps/edge/internal/openai/hot_path_direct_test.go`

```text
```

Exit status: 0

### Diff integrity

Command: `git diff --check`

```text
```

Exit status: 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 Ownership

| Section | Owner | Note |
|---------|-------|------|
| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| 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 |
| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section |
| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content |
| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan |
| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry |
| Code Review Result | Review agent appends | Not included in stub |

## Code Review Result

- Overall Verdict: FAIL
- Dimension Assessment:
  - Correctness: Fail
  - Completeness: Fail
  - Test Coverage: Fail
  - API Contract: Fail
  - Code Quality: Pass
  - Implementation Deviation: Fail
  - Verification Trust: Pass
  - Spec Conformance: Fail
- Findings:
  - Required — `apps/edge/internal/openai/hot_path_stage_stream.go:123` and `apps/edge/internal/openai/hot_path_dispatch.go:133`: both normalized consumers bind the current event's `openai_response_id` with a helper that treats an empty value as a no-op, then call `require()` against the identity cached from an earlier event. A later visible delta or the complete event can therefore omit the required metadata and still be released/accepted, contrary to the inner wire contract and REVIEW_API-1's event-by-event fail-closed requirement. Require a non-empty metadata value on every `delta`, `reasoning_delta`, and `complete`, verify it equals the bound identity, and add selector/live-stage regressions where the first event is valid but a later visible or complete event omits the key.
  - Required — `apps/edge/internal/openai/hot_path_stage_stream.go:619` and `apps/edge/internal/openai/hot_path_light.go:878`: the live OpenAI decoder parses `finish_reason` but never records or projects it, and the Anthropic decoder likewise ignores `message_delta.stop_reason`. `stageOutput()` consequently defaults a no-tool live stage to `stop`; the Light state machine can advance to review or final cleanup even when the provider ended the stage with `length`/`max_tokens`. Preserve the provider terminal reason in the stage projection, terminate the outer Chat turn with `length` instead of advancing the Light flow when that reason is reported, and add a progressive Light regression that flushes content before a provider `length` terminal and then emits exactly one public `finish_reason:"length"` plus `[DONE]`.
- Routing Signals:
  - `review_rework_count=2`
  - `evidence_integrity_failure=false`
- Next Step: Invoke the plan skill in `prepare-follow-up` mode with these raw findings and fresh verification evidence, then archive this pair and materialize the routed follow-up pair.
