<!-- task=m-iop-hot-path-one-shot-execution/15+13,14_error_cancel plan=0 tag=API milestone-task=error-cancel -->

# Hot Path endpoint error, cancel, and length semantics

## For the Implementing Agent

구현 후 `CODE_REVIEW-cloud-G10.md`의 구현 담당 섹션과 실제 출력까지 채우고 active 파일을 유지한다. 차단 시 blocker/명령/출력/재개 조건만 기록하며 사용자 질문, 상태 판정, archive, `complete.log` 작성은 금지한다.

## Background

Cleanup은 primary error precedence와 caller cancellation을 갖지만 새 outer stream 및 양 endpoint codec 전체의 error/cancel/length 조합은 아직 하나의 표준 의미로 닫히지 않는다. 이 packet은 custom partial-success 없이 pre/post-commit endpoint 결과와 hidden work 중단을 일치시킨다.

## Analysis

### Files Read

- `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-hot-path-one-shot-execution/SDD.md`
- `apps/edge/internal/openai/hot_path_cleanup.go`
- `apps/edge/internal/openai/hot_path_dispatch.go`
- `apps/edge/internal/openai/hot_path_light.go`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/anthropic_stream.go`
- `apps/edge/internal/openai/chat_handler.go`
- `apps/edge/internal/openai/normalized_sse.go`
- `apps/edge/internal/openai/server.go`
- `apps/edge/internal/openai/hot_path_cleanup_test.go`
- `apps/edge/internal/openai/cancellation_routes_test.go`
- `apps/edge/internal/openai/chat_stream_session_test.go`
- `agent-contract/outer/openai-compatible-api.md`
- `agent-contract/outer/anthropic-compatible-api.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`

### SDD Criteria

- 승인 SDD, `milestone-task=error-cancel`, S13.
- Evidence Map S13의 endpoint별 error/cancel/length table을 구현 단위로 사용한다. primary error 보존, cleanup best effort, abort 후 no hidden call, length terminal과 no partial-success가 oracle이다.

### Verification Context

- handoff 없음. local edge profile, fresh race tests. repo/branch/HEAD=`/config/workspace/iop-s0`, `feature/iop-hot-path-one-shot-execution`, `6650e9f70d0104220d8077dd1d469b6a1facb9da`.
- fault fixtures로 모든 경로를 결정적으로 재현하므로 외부 runtime은 필요 없다.

### Test Coverage Gaps

- cleanup tests는 primary error/concurrency를 검증하지만 endpoint×commit-state×failure-source matrix, output-cap length terminal, 양 protocol wire terminal은 빠져 있다.

### Symbol References

- rename/remove 없음. predecessor codec의 error/terminal hook을 확장한다.

### Split Judgment

- stable contract: common terminal disposition → endpoint-standard pre/post-commit result.
- predecessors 13과 14의 active `complete.log`는 현재 missing이며 둘 다 구현 전에 필요하다.

### Scope Rationale

- 새 status/type을 만들지 않는다. observability field와 live agent smoke는 16/17로 제외한다.

### Final Routing

- evaluation_mode=write, finalizer=`finalize-task-policy.sh pair`.
- build closures 모두 true, scores=2/2/2/1/2, G09, grade-boundary → `PLAN-cloud-G09.md`.
- review closures 모두 true, scores=2/2/2/2/2, G10, official-review → `CODE_REVIEW-cloud-G10.md`.
- `large_indivisible_context=false`; risks=`temporal_state,concurrent_consistency,boundary_contract,structured_interpretation,variant_product`(5); recovery=0/false; capability gap 없음.

## Implementation Checklist

- [ ] [API-1] Centralize Hot Path terminal disposition so provider/config/context/timeout/cancel/output-cap outcomes stop hidden work and map to each endpoint's standard pre/post-commit shape exactly once.
- [ ] [API-2] Add the endpoint-by-outcome table and concurrent cancel/complete regressions, then run targeted plus SDD common verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Standard terminal disposition

**Problem:** `hot_path_cleanup.go:267` writes a completed terminal intent, while handler collection errors call endpoint writers separately. With progressive release, commit state determines the legal wire error and cancellation must prevent later repair/cleanup dispatch.

**Solution:** Add a typed internal disposition (`success`, `tool_turn`, `length`, `provider_error`, `validation_error`, `timeout`, `caller_cancel`) consumed by the common outer turn and endpoint codecs. Propagate the active stage dispatch/cancel function from `submitHotPathStage` through local/review execution so the terminal arbiter can atomically win once, cancel the exact in-flight stage, and call `CancelRun` only for dispatched active work. Caller cancel writes no further bytes and detaches state; timeout/provider/context error preserve primary error through permissible cleanup; output cap commits native length semantics, not an error or partial success. Endpoint codecs, rather than handlers alone, own the post-commit wire error.

Before (`hot_path_cleanup.go:267`):

```go
func (s *Server) writeHotPathTerminal(..., terminal hotPathTerminalIntent) error
```

After:

```go
func (s *Server) finishHotPathTurn(ctx context.Context, turn *hotPathOuterTurn, disposition hotPathDisposition) error
```

**Modified Files and Checklist:**

- [ ] Modify `apps/edge/internal/openai/hot_path_cleanup.go` to produce typed dispositions and preserve primary-error/cleanup ordering.
- [ ] Modify `apps/edge/internal/openai/hot_path_terminal_control.go` to atomically arbitrate terminal, cancel current stage, and reject post-terminal events.
- [ ] Modify `apps/edge/internal/openai/hot_path_dispatch.go` and `apps/edge/internal/openai/hot_path_light.go` to retain the exact active dispatch/cancel handle and stop subsequent stage/repair/cleanup work after terminal ownership is lost.
- [ ] Modify `apps/edge/internal/openai/anthropic_handler.go`, `anthropic_stream.go`, `chat_handler.go`, and `normalized_sse.go` so all preset terminal outcomes delegate to the common disposition and each codec owns its standard post-commit shape.

**Test Strategy:** API-2 supplies the cross-product; retain cleanup and ordinary cancellation tests.

**Verification:** `go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPath(EndpointTerminalMatrix|CancelCompleteRace|Cleanup)'` exits 0.

### [API-2] Endpoint outcome matrix

**Problem:** No single test proves S13 across both endpoints and response commit states.

**Solution:** Table over endpoint `{anthropic,openai}`, response `{uncommitted,committed}`, source `{write-unavailable,provider-error,context-error,timeout,cancel,output-cap}`, stage `{selector,local,review,cleanup}`. Assert exact HTTP/SSE event type/finish reason, primary error precedence, zero custom partial status, one CancelRun when warranted, no hidden follow-up after abort, and one terminal winner under barriers.

**Modified Files and Checklist:**

- [ ] Add `apps/edge/internal/openai/hot_path_error_cancel_test.go` with `TestHotPathEndpointTerminalMatrix` and `TestHotPathCancelCompleteRace`.
- [ ] Fill `agent-task/m-iop-hot-path-one-shot-execution/15+13,14_error_cancel/CODE_REVIEW-cloud-G10.md`.

**Test Strategy:** New table/race tests mandatory. Exact wire assertions must use existing contract status/type names; forbid `partial_success`, `review_unavailable`, or `repair_limit`.

**Verification:** run Final Verification; all rows and race detector pass.

## Dependencies and Execution Order

1. `13+12_anthropic_gate` must produce its active `complete.log`.
2. `14+12_chat_gate` must produce its active `complete.log`.
3. Implement API-1, then API-2.

## Modified Files Summary

| File | Item |
|---|---|
| `apps/edge/internal/openai/hot_path_cleanup.go` | API-1 |
| `apps/edge/internal/openai/hot_path_terminal_control.go` | API-1 |
| `apps/edge/internal/openai/hot_path_dispatch.go` | API-1 |
| `apps/edge/internal/openai/hot_path_light.go` | API-1 |
| `apps/edge/internal/openai/anthropic_handler.go` | API-1 |
| `apps/edge/internal/openai/anthropic_stream.go` | API-1 |
| `apps/edge/internal/openai/chat_handler.go` | API-1 |
| `apps/edge/internal/openai/normalized_sse.go` | API-1 |
| `apps/edge/internal/openai/hot_path_error_cancel_test.go` | API-2 |
| `agent-task/m-iop-hot-path-one-shot-execution/15+13,14_error_cancel/CODE_REVIEW-cloud-G10.md` | API-2 |

## Final Verification

```bash
go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPath(EndpointTerminalMatrix|CancelCompleteRace|Cleanup)|Test(ChatCompletion|Responses|StreamChatCompletion).*(Cancel|Timeout)'
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, no race/custom partial status/post-cancel dispatch, exactly one native terminal, empty diff check. Cached output is not acceptable.

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