<!-- task=m-iop-owned-single-request-agent-execution/06+05_stream_terminal plan=2 tag=API milestone-task=stream-terminal -->

# Single-request Anthropic SSE Projection

## For the Implementing Agent

Do not start until packet 05 has `complete.log`. Implement this plan exactly within the listed write boundary, run every verification command, fill all implementation-owned sections of `CODE_REVIEW-cloud-G10.md` with actual notes and stdout/stderr, keep the active pair in place, and report ready for review. Finalization belongs only to the code-review skill. If blocked, record exact blocker evidence, attempted commands/output, and the resume condition; do not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`.

## Archive Evidence Snapshot

- Superseded pair: `plan_cloud_G09_1.log`, `code_review_cloud_G10_1.log`.
- The superseded pair contained no implementation evidence or review verdict; implementation has not started.
- Fresh-review correction: preserve the closed repair-aware projector scope, and replace the broad archive scan with the exact predecessor candidate pattern required by the split dependency protocol.

## Background

The generic Anthropic Hot Path codec can expose normalized reasoning and tool blocks and is scoped to a caller turn. SDD S03 requires a stricter endpoint projector for the single-request coordinator: one envelope, fixed redacted plan/work/review/repair progress, liveness ping, no private internal wire, and exactly one endpoint-native terminal after all internal work.

## Analysis

### Files Read

- `AGENTS.md`
- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/common/rules-agent-spec.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/iop-owned-single-request-agent-execution.md`
- `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/anthropic_stream.go`
- `apps/edge/internal/openai/hot_path_direct.go`
- `apps/edge/internal/openai/hot_path_anthropic_gate_test.go`
- `apps/edge/internal/openai/request_identity_handler_test.go`
- `agent-contract/outer/anthropic-compatible-api.md`
- `agent-spec/input/openai-compatible-surface.md`
- `agent-spec/runtime/stream-evidence-gate.md`

### SDD Criteria

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`; status approved and implementation lock released.
- First-line Milestone task: `stream-terminal`; targeted Acceptance Scenario: S03.
- Evidence Map row S03 requires fragmented multi-stage SSE with fixed redacted progress/ping, one envelope, collision-free blocks, forbidden-private-value absence, and exactly one terminal. Those facts directly shape API-1/API-2 and the exact-wire/race commands in Final Verification.

### Verification Context

- No separate verification handoff was supplied. Repository-native fallback came from the current Anthropic codec/framing helper, Hot Path exact-wire and terminal race tests, Edge/platform test profiles, outer contract, and approved SDD.
- Precondition: packet 05 completion, which transitively includes packet 03's coordinator. Constraints: in-process deterministic writer/manual tick verification only; no external provider/runner. Gap: real Claude liveness remains later Milestone smoke evidence.
- Commands use exact-wire race tests, marked/generic endpoint regressions, deterministic doc search, `go vet`, full Edge/streamgate regression, and `git diff --check`. Confidence is high for framing/privacy/concurrency; real network latency remains outside scope.

### Wire and Concurrency Findings

- One `message_start` uses the coordinator message id and requested public model.
- Fixed Edge-owned summaries may represent plan, work, review, and detected defect/repair (`repairing`). `finalizing`/cleanup remains internal, and arbitrary internal strings cannot become progress.
- `event: ping` is permitted only before terminal and does not open content blocks.
- Success emits ordered final text, one `message_delta` with `end_turn`, then one `message_stop`. Streamed error/cancel emits one sanitized `error` and never a success terminal.
- One serialized writer/terminal lock owns every content index, ping, flush, and terminal decision. Ticker shutdown is joined before handler return.

### Test Coverage Gaps

- Existing generic codec tests intentionally permit reasoning/tool deltas and therefore cannot prove this closed privacy boundary.
- No test covers repair progress, pings across delayed stages, one envelope, forbidden sentinels, monotonic indices, or ping/final/cancel races.

### Symbol References

- No symbol is renamed or removed. `writeDirectAnthropicEvent` is reused for framing only. `anthropicHotPathCodec` remains the generic codec and is not a valid projector for closed single-request events.

### Split Judgment

- Indivisible invariant: one serialized projector owns envelope, content indices, pings, flushes, and terminal. Splitting ping and terminal ownership would permit post-terminal writes.
- Predecessor index 05 resolves to `agent-task/m-iop-owned-single-request-agent-execution/05+03_single_ingress/`; its `complete.log` is currently missing, so implementation remains pending and unambiguous. Packet 03's coordinator is a transitive prerequisite.

### Scope Rationale

- Exclude ordinary Anthropic relay, Chat bridge, generic Hot Path codec, Stream Evidence Gate filters, provider decoding, Node wire, and workspace/tool execution because this packet projects already-classified service events only.
- Never emit provider reasoning, tool names/arguments/results, route/provider/credential ids, workspace paths, raw commands, or internal stage terminals.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer `finalize-task-policy.sh` in `pair` mode.
- Build closures are true; scores 2/2/2/1/2 = G09; base/final route `grade-boundary`; lane `cloud`; canonical filename `PLAN-cloud-G09.md`.
- Build signals: `large_indivisible_context=false`; positive loop risks `temporal_state`, `concurrent_consistency`, `boundary_contract`, `structured_interpretation`, `variant_product` (5); `review_rework_count=0`; `evidence_integrity_failure=false`; no capability gap.
- Review closures are true; scores 2/2/2/2/2 = G10; route `official-review`; lane `cloud`; canonical filename `CODE_REVIEW-cloud-G10.md`.

## Dependencies and Execution Order

1. Verify packet 05 completion evidence and use the marked endpoint plus packet 03's exact public progress/result types.
2. Build and race-test the isolated projector.
3. Integrate the projector/ticker into marked streaming only.
4. Prove exact wire privacy and ordinary path compatibility before updating docs/specs.

## Implementation Checklist

- [ ] Implement a serialized single-request Anthropic SSE projector with one envelope, fixed plan/work/review/repair summaries, liveness ping, final text/error, and exactly-once terminal ownership.
- [ ] Integrate it only with the marked coordinator stream, stop and join liveness before terminal/return, acknowledge service completion only after the one wire terminal succeeds, and prove one POST plus no private wire across fragmented multi-stage and repair events.
- [ ] Preserve ordinary Anthropic/Hot Path behavior and synchronize the outer contract and current specs without expanding generic Stream Evidence Gate semantics.
- [ ] Run dependency, exact-wire race, package, vet, full Edge/streamgate regression, and `git diff --check` verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Implementation Plan

### [API-1] Add a privacy-closed Anthropic stream projector

**Problem**

- `apps/edge/internal/openai/anthropic_stream.go:339` owns a generic codec that can accept reasoning and tool fragments, which is too permissive for the fixed single-request privacy boundary.
- `apps/edge/internal/openai/hot_path_direct.go:474` provides framing but no closed progress vocabulary, liveness ping, or unified ping/terminal lock.

**Solution**

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

```go
type anthropicHotPathCodec struct {
    mu sync.Mutex

    w         http.ResponseWriter
    model     string
    stream    bool
    requestID string
}
```

After, in an isolated file:

```go
type singleRequestAnthropicStream struct {
    mu        sync.Mutex
    started   bool
    terminal  bool
    nextBlock int
}
```

Accept only predecessor-defined public enums/results. Reuse `writeDirectAnthropicEvent` for framing only. Map plan/work/review/repair to fixed Edge summaries, keep finalizing/cleanup internal, reject unknown phases, serialize block indices/pings/flush/terminal, and make every post-terminal call a no-op returning the established result.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/openai/single_request_anthropic_stream.go` — implement the closed projector, fixed phase map including repair, ping, final/error, and serialized terminal state.
- [ ] `apps/edge/internal/openai/single_request_anthropic_stream_test.go` — parse exact wire and cover one envelope/terminal, monotonic blocks, repair summary, ping ordering, forbidden sentinels, and concurrent terminal races.

**Test Strategy**

- Add `TestSingleRequestAnthropicStreamOneEnvelopeOneTerminal`, `...PingAndProgressOrdering`, `...RepairSummary`, `...RedactsPrivateEvents`, and `...ErrorTerminalRace` with a deterministic flushing recorder and sentinel fixtures.
- Run this test prefix under the race detector because every writer/terminal path is concurrent-sensitive.

**Verification**

- `go test -race ./apps/edge/internal/openai -run 'TestSingleRequestAnthropicStream' -count=1`
- Expected: exact event counts/order and privacy assertions pass with no race or duplicate terminal.

### [API-2] Pump coordinator progress and liveness on the same request

**Problem**

- `apps/edge/internal/openai/anthropic_handler.go:66` has no marked-stream pump spanning all internal stages.
- `apps/edge/internal/openai/anthropic_handler.go:66` owns the `ResponseWriter` lifetime, so a standalone ticker could write after final/cancel or handler return unless shutdown and terminal ownership are explicitly joined there.

**Solution**

Before (`apps/edge/internal/openai/anthropic_handler.go:66`):

```go
func (s *Server) handleAnthropicMessages(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        writeAnthropicError(w, http.StatusMethodNotAllowed, "invalid_request_error", "method not allowed")
        return
    }
}
```

After, inside the packet 05 marked branch:

```go
if dispatch.SingleRequest != nil && request.Stream {
    return s.handleAnthropicSingleRequestStream(w, r, dispatch, request)
}
```

Start the closed projector and execute the coordinator with its public progress callback. Use an injectable ticker factory/manual channel. Stop, signal, and join the ping worker before final/error and before handler return. Acknowledge the predecessor execution handle as completed only after `message_stop` is written successfully; terminal write failure or caller disconnect selects failure/cancellation and cannot synthesize success. Marked non-stream behavior stays unchanged.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/openai/anthropic_handler.go` — select the projector for marked streaming and own coordinator/ticker lifetime.
- [ ] `apps/edge/internal/openai/single_request_anthropic_stream.go` — add the deterministic progress/ticker pump and shutdown join.
- [ ] `apps/edge/internal/openai/single_request_anthropic_stream_test.go` — cover delayed fragmented stages, repair, manual pings, success acknowledgement after stop, terminal write failure, disconnect, terminal order, and one real handler POST.

**Test Strategy**

- Add `TestAnthropicSingleRequestStreamingUsesOnePost`, `...AcknowledgesAfterMessageStop`, `...TerminalWriteFailureDoesNotComplete`, `...StopsPingBeforeTerminal`, and `...DisconnectStopsWriter` using packet 05's fake single-request capability plus manual ticks.
- Rerun `TestHotPathAnthropic*` unchanged to prove generic codec behavior is not weakened.

**Verification**

- `go test ./apps/edge/internal/openai -run 'Test(AnthropicSingleRequestStreaming|AnthropicSingleRequestStream|HotPathAnthropic)' -count=1`
- Expected: one handler POST holds the stream across delayed stages; pings cease before terminal/return; generic tests remain unchanged.

### [API-3] Synchronize SSE and compatibility contracts

**Problem**

- `agent-contract/outer/anthropic-compatible-api.md:211` permits generic thinking and `tool_use` response blocks without a closed marked subset.
- `agent-spec/input/openai-compatible-surface.md:132` and `agent-spec/runtime/stream-evidence-gate.md:97` do not define marked repair progress, ping ownership, or terminal/privacy exclusivity.

**Solution**

Before (`agent-contract/outer/anthropic-compatible-api.md:211`):

```markdown
- `model`: Authorized virtual presets echo the requested virtual model. Ordinary native responses preserve the provider response model, while Chat bridge responses use the converted Anthropic request model.
- `content`: text, thinking, tool_use block array.
- `stop_reason`: `end_turn`, `max_tokens`, `tool_use`, `stop_sequence` 중 하나.
```

After, add a separate marked SSE subsection and matching spec rows:

```markdown
The marked single-request stream keeps one message envelope, emits only fixed
plan/work/review/repair summaries and `event: ping`, excludes private reasoning/tool
wire, and commits exactly one success or sanitized error terminal.
```

Document exact event/order rules, requested model retention, ping shutdown, forbidden private values, exclusive success/error terminal, and generic Stream Evidence Gate non-expansion. Do not claim real-provider/Claude smoke.

**Modified Files and Checklist**

- [ ] `agent-contract/outer/anthropic-compatible-api.md` — define the marked SSE subset, repair progress, privacy, and terminal/error rules.
- [ ] `agent-spec/input/openai-compatible-surface.md` — synchronize endpoint integration and tests.
- [ ] `agent-spec/runtime/stream-evidence-gate.md` — record the separate service-to-endpoint projection boundary and generic-filter non-expansion.

**Test Strategy**

- No standalone documentation test. API-1/API-2 exact-wire parser and forbidden-sentinel assertions are the executable oracle.

**Verification**

- `rg --sort path -n 'single-request|repair|event: ping|message_start|message_stop|private|tool_use' agent-contract/outer/anthropic-compatible-api.md agent-spec/input/openai-compatible-surface.md agent-spec/runtime/stream-evidence-gate.md`
- Expected: allowed/forbidden wire behavior is explicit and matches the exact-wire tests.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/openai/single_request_anthropic_stream.go` | API-1, API-2 |
| `apps/edge/internal/openai/single_request_anthropic_stream_test.go` | API-1, API-2 |
| `apps/edge/internal/openai/anthropic_handler.go` | API-2 |
| `agent-contract/outer/anthropic-compatible-api.md` | API-3 |
| `agent-spec/input/openai-compatible-surface.md` | API-3 |
| `agent-spec/runtime/stream-evidence-gate.md` | API-3 |
| `agent-task/m-iop-owned-single-request-agent-execution/06+05_stream_terminal/CODE_REVIEW-cloud-G10.md` | API-1, API-2, API-3 |

## Final Verification

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/05+03_single_ingress/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/05+03_single_ingress/complete.log' | wc -l)" -eq 1`
2. `go test -race ./apps/edge/internal/openai -run 'TestSingleRequestAnthropicStream' -count=1`
3. `go test ./apps/edge/internal/openai -run 'Test(AnthropicSingleRequestStreaming|AnthropicSingleRequestStream|HotPathAnthropic)' -count=1`
4. `rg --sort path -n 'single-request|repair|event: ping|message_start|message_stop|private|tool_use' agent-contract/outer/anthropic-compatible-api.md agent-spec/input/openai-compatible-surface.md agent-spec/runtime/stream-evidence-gate.md`
5. `go test -race ./apps/edge/internal/openai -count=1`
6. `go vet ./apps/edge/...`
7. `go test ./apps/edge/... ./packages/go/streamgate/... -count=1`
8. `git diff --check`

Expected: predecessor evidence exists; exact-wire/race/privacy tests pass; pings stop before one terminal; ordinary Anthropic/Hot Path regressions pass. Actual Claude/provider smoke remains outside this packet.

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