<!-- task=m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress plan=3 tag=REVIEW_API -->

# Stop Anthropic bridge output at the first stream terminal

## For the Implementing Agent

Filling the implementation-owned sections of `CODE_REVIEW-cloud-G06.md` is the mandatory final implementation step. Implement the scoped fix, run every verification command, record actual notes and stdout/stderr, keep the active files in place, and report ready for review. If blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields. Do not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`; finalization remains review-agent-only.

## Background

The Messages ingress implementation and its normal regression suite pass, but review reproduced an Anthropic Chat-bridge ordering defect. When one upstream BODY frame contains `[DONE]` and another SSE data event, `Feed` emits `message_stop` and then processes the later event, reopening content output after the terminal. The follow-up is limited to closing that request-local state transition and adding the missing regression.

## Archive Evidence Snapshot

- Direct predecessor PASS evidence: `agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/01_protocol_core/complete.log`.
- First plan/review logs: `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/plan_cloud_G09_01.log` and `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/code_review_cloud_G09_01.log`.
- Current plan/review archive targets: `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/plan_cloud_G09_02.log` and `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/code_review_cloud_G09_02.log`.
- Current verdict: `FAIL`; findings: Required=1, Suggested=0, Nit=0.
- Required finding: `apps/edge/internal/openai/anthropic_stream.go:67-83` continues consuming buffered SSE events after `[DONE]` or an error makes the stream terminal, allowing content after the terminal event.
- Verification evidence: focused surface/native/bridge tests, Edge vet/tests, Node tests, route inspection, diff hygiene, and the isolated fake Lemonade E2E pass; a focused reviewer reproducer fails by showing `message_stop` followed by a `late` content block.
- Roadmap carryover: `messages-surface`, `messages-native`, and `messages-chat-bridge` remain unchecked until this follow-up passes.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/multi-provider-protocol-profile-native-messages.md`
- Milestone link: [Milestone document](agent-roadmap/phase/operational-observability-provider-management/milestones/multi-provider-protocol-profile-native-messages.md)
- Task ids:
  - `messages-surface`: canonical/alias routes, principal auth, Anthropic model schema, and count-tokens
  - `messages-native`: native Messages raw tunnel preservation
  - `messages-chat-bridge`: Messages-to-Chat semantic and streaming bridge
- Completion mode: check-on-pass

## Analysis

### Files Read

- `apps/edge/internal/openai/anthropic_stream.go`
- `apps/edge/internal/openai/anthropic_bridge.go`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/anthropic_native.go`
- `apps/edge/internal/openai/anthropic_types.go`
- `apps/edge/internal/openai/routes.go`
- `apps/edge/internal/openai/principal.go`
- `apps/edge/internal/openai/server.go`
- `apps/edge/internal/openai/anthropic_bridge_test.go`
- `apps/edge/internal/openai/anthropic_native_test.go`
- `apps/edge/internal/openai/anthropic_surface_test.go`
- `apps/edge/internal/openai/provider_test_support_test.go`

### SDD Criteria

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/multi-provider-protocol-profile-native-messages/SDD.md`, status `[Approved]`, lock released.
- Targeted scenarios: S05 `messages-surface`, S06 `messages-native`, and S07 `messages-chat-bridge`; the defect is specifically in S07's requirement to restore supported semantics and the response state machine's no-successor `response/terminal` state.
- Evidence Map: the S05-S07 row requires direct Edge fixtures, native tunnel byte/SSE evidence, and Messages-to-Chat golden tests. This follow-up adds the missing same-frame terminal fixture and reruns the focused bridge plus full Edge/Node evidence while retaining the already implemented S05/S06 behavior.

### Verification Context

- No separate `verification_context` handoff was supplied. Repository rules, the active plan/review pair, the cited prior logs, the approved SDD, current source/tests, and fresh reviewer commands supplied the evidence.
- Environment: `/config/.local/bin/go`, Go 1.26.2, GOROOT `/config/opt/go`; the host `/tmp` mount is no-exec for Go test binaries, so Go commands use `/config/workspace/iop-s0/.local/gotmp-g09-followup` and an explicit cache under `/config/.cache`.
- Fresh reviewer results: the three focused Anthropic suites, `go vet ./apps/edge/...`, `go test -count=1 ./apps/edge/...`, `go test -count=1 ./apps/node/...`, `IOP_LEMONADE_MODE=fake ./scripts/e2e-openai-lemonade.sh`, route inspection, and `git diff --check` pass. The first concurrent cold-cache E2E attempt exceeded its fake-server startup deadline; an isolated warmed rerun passed.
- Gap and confidence: existing tests omit post-terminal data within the same Feed call. The focused temporary reproducer deterministically fails and was removed after capture, so confidence is high and no external verification or user-controlled capability is required.

### Test Coverage Gaps

- Normal fragmented Chat SSE, `[DONE]` followed by tunnel END, content ordering, tools, thinking, usage, and exactly one ordinary `message_stop` are covered by `TestAnthropicChatBridgeStreamFragmentationOrderAndTerminal`.
- Later data after a terminal marker in the same BODY frame is not covered. Add integrated table cases for `[DONE]` and upstream error terminals, assert no later content is emitted, and assert the terminal event is final and occurs once even when tunnel END follows.

### Symbol References

None. No symbol is renamed or removed.

### Split Judgment

Keep one plan. The state-loop guard and its integrated regression form one compact ordering invariant; splitting production and test changes would not produce independently passing work. Split predecessor `01_protocol_core` is satisfied by archived `agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/01_protocol_core/complete.log`.

### Scope Rationale

Only the Chat SSE state machine and its bridge regression test are implementation scope. Native Messages relay, request transforms, auth/routes/models/counting, contracts/specs, fixtures unrelated to this terminal case, and roadmap state are excluded because fresh evidence shows no defect there and runtime owns roadmap mutation.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer `finalize-task-policy.sh`, mode `pair`.
- Build closures: scope/context/verification/evidence/ownership/decision are all true. Scores are scope=1, state=1, blast=2, evidence=0, verification=1, yielding G05. Base basis is `local-fit`; `large_indivisible_context=false`; matched loop risks are `temporal_state`, `boundary_contract`, and `structured_interpretation` (count 3); `review_rework_count=2`; `evidence_integrity_failure=false`; recovery boundary promotes the build to `recovery-boundary`, cloud, `PLAN-cloud-G05.md`.
- Review closures are all true. Scores are scope=1, state=1, blast=2, evidence=1, verification=1, yielding G06; route is `official-review`, cloud, `CODE_REVIEW-cloud-G06.md` with Codex `gpt-5.6-sol` at xhigh reasoning.
- No capability gap exists.

## Implementation Checklist

- [ ] Stop `anthropicBridgeStream.Feed` immediately after the first successful terminal transition and discard buffered post-terminal SSE bytes.
- [ ] Add integrated same-frame `[DONE]`/error terminal regressions that include later data and tunnel END, asserting the terminal event is final and emitted once.
- [ ] Run the focused bridge, full Edge/Node, vet, fake Lemonade, and diff-hygiene verification commands.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_API-1] Enforce the Anthropic bridge terminal boundary

#### Problem

`apps/edge/internal/openai/anthropic_stream.go:67-83` checks `s.stopped` only at entry. After `consumeSSEEvent` handles `[DONE]` through `Finish` or handles an upstream error through `Error`, the loop continues consuming any event already buffered in the same Feed call. A later content delta therefore appears after `message_stop` or an error terminal, violating the approved SDD's no-successor terminal state and ordered Anthropic output contract.

Before (`apps/edge/internal/openai/anthropic_stream.go:73`):

```go
for {
	index := bytes.Index(s.pendingSSE, []byte("\n\n"))
	if index < 0 {
		return nil
	}
	event := append([]byte(nil), s.pendingSSE[:index]...)
	s.pendingSSE = s.pendingSSE[index+2:]
	if err := s.consumeSSEEvent(event); err != nil {
		return err
	}
}
```

#### Solution

After each consumed event, check the request-local terminal state. If terminal, clear `pendingSSE` and return without parsing any later data from the current frame. Keep the existing idempotent entry guard so later BODY frames and tunnel END also remain no-ops. Do not special-case only `[DONE]`; the guard must cover every successful transition that sets `stopped`, including upstream error events.

After (representative):

```go
if err := s.consumeSSEEvent(event); err != nil {
	return err
}
if s.stopped {
	s.pendingSSE = nil
	return nil
}
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/anthropic_stream.go`: stop the current Feed loop at the first terminal and discard later buffered bytes.
- [ ] `apps/edge/internal/openai/anthropic_bridge_test.go`: add integrated same-frame terminal cases through the HTTP/tunnel path.
- [ ] `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/CODE_REVIEW-cloud-G06.md`: record implementation decisions and actual verification output.

#### Test Strategy

Add `TestAnthropicChatBridgeStreamStopsAtTerminalWithinFrame` in `apps/edge/internal/openai/anthropic_bridge_test.go`. Use table cases for `[DONE]` and an upstream error event, put a `late` content delta after the terminal in the same tunnel BODY frame, then send tunnel END. Assert the output contains no `late` content or post-terminal content block events, the expected terminal is the final event, and it occurs exactly once. Keep `TestAnthropicChatBridgeStreamFragmentationOrderAndTerminal` as the normal fragmented-stream golden regression.

#### Verification

```bash
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go test -count=1 ./apps/edge/internal/openai -run 'TestAnthropicChatBridge(StreamFragmentationOrderAndTerminal|StreamStopsAtTerminalWithinFrame)$'
```

Expected: both normal fragmentation and same-frame terminal boundary cases pass, with no post-terminal output.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/edge/internal/openai/anthropic_stream.go` | REVIEW_API-1 |
| `apps/edge/internal/openai/anthropic_bridge_test.go` | REVIEW_API-1 |
| `agent-task/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/CODE_REVIEW-cloud-G06.md` | REVIEW_API-1 |

## Final Verification

Prepare executable Go cache/temp paths once:

```bash
mkdir -p /config/.cache/iop-g09-followup/cache /config/workspace/iop-s0/.local/gotmp-g09-followup
```

Run fresh focused and regression checks:

```bash
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go test -count=1 ./apps/edge/internal/openai -run 'TestAnthropicChatBridge(StreamFragmentationOrderAndTerminal|StreamStopsAtTerminalWithinFrame)$'
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go test -count=1 ./apps/edge/internal/openai -run 'TestAnthropicChatBridge'
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go vet ./apps/edge/...
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go test -count=1 ./apps/edge/...
GOCACHE=/config/.cache/iop-g09-followup/cache GOTMPDIR=/config/workspace/iop-s0/.local/gotmp-g09-followup /config/.local/bin/go test -count=1 ./apps/node/...
IOP_LEMONADE_MODE=fake ./scripts/e2e-openai-lemonade.sh
git diff --check
```

Expected: the focused terminal regression, all Chat bridge tests, Edge vet/tests, Node tests, fake Lemonade E2E, and diff hygiene pass. Go test cache output is not accepted because every test command uses `-count=1`.

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