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

# Code Review Reference - API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is mandatory.** Fill implementation-owned evidence and stop with active files. Review finalization is review-agent-only.

## Overview

date=2026-08-03
task=m-iop-hot-path-one-shot-execution/16+14,15_terminal_disposition, plan=2, tag=API

## Archive Evidence Snapshot

- Plan/review 1 was superseded before implementation; it contains no implementation verdict/evidence.

## For the Review Agent

Verify source and race evidence, archive to `code_review_cloud_G10_2.log` and `plan_cloud_G09_2.log`, then finalize by verdict. Preserve `milestone-task=error-cancel` on PASS.

## Implementation Item Completion

| Item | Status |
|---|---|
| API-1 Disposition and cancellation ownership | [x] |
| API-2 Terminal race evidence | [x] |

## Implementation Checklist

- [x] [API-1] Normalize terminal dispositions and wire one exact active-stage cancellation/cleanup handoff across direct/light transitions.
- [x] [API-2] Add cancel/timeout/error/length/tool/success race and exact-target regression evidence.
- [x] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Review-Only Checklist

- [x] Append verdict/routing signals and verify findings/dimensions.
- [x] Archive review/plan to suffix `2`; verify `.gitignore` managed block.
- [x] On PASS write `complete.log`, preserve metadata, archive child; on WARN/FAIL write directed state without completion.

## Deviations from Plan

- Added minimal caller-codec cancellation glue in `normalized_sse.go` and `anthropic_stream.go` so a canceled initial selector turn is treated as consumed and cannot synthesize endpoint bytes after exact active-run cancellation.
- Retained the buffered selector/non-stream collectors for pre-classification compatibility, but wrapped them in the same generation-fenced active-stage controller used by progressive stages. This preserves provider metadata and prevents invalid pre-classification tool output from entering the caller accumulator.

## Key Design Decisions

- Defined the closed disposition vocabulary `success`, `tool_turn`, `length`, `provider_error`, `validation_error`, `timeout`, and `caller_cancel`, with cause, source, stage, and generation ownership.
- Separated logical disposition election from public HTTP-turn commitment. This lets timeout/provider/validation intent remain the single winner while a caller-owned cleanup tool frontier is emitted before the stored primary terminal.
- Registered one active stage per outer turn generation. Registration fails until the prior controller closes, and the Core attempt plus context watcher share one action-once controller, so close/cancel races cannot duplicate `CancelRun`.
- Detached `CancelRun(CANCEL_RUN)` from a canceled caller context and preserved the exact active dispatch tuple (`node`, `run`, `adapter`, `target`, `session`). Stale generation callbacks and duplicate terminal attempts are no-ops.
- Stored typed disposition in Light cleanup and orphan state while retaining legacy coordinator terminal-class strings for existing TTL/observation compatibility.

## Reviewer Checkpoints

- Confirm closed dispositions and exactly one winner under cancel/complete/error/cap races.
- Confirm cancellation targets only the exact current stage once and stale stage handles/callbacks are ignored.
- Confirm caller cancel is wire-silent and cleanup/orphan receives one typed terminal responsibility.

## Verification Results

### Targeted

Command: `go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPath(TerminalDisposition|ActiveStageCancel|CancelCompleteRace|Cleanup)'`

Output:

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

Exit status: `0`.

### Common regression

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

Output:

```text
ok  	iop/packages/go/streamgate	2.206s
ok  	iop/packages/go/config	1.817s
ok  	iop/apps/edge/internal/openai	13.296s
ok  	iop/apps/edge/internal/service	7.600s
```

Exit status: `0`.

### Diff

Command: `git diff --check`

Output: no stdout/stderr.

Exit status: `0`.

## Section Ownership

Implementer owns completion status, deviations, decisions, and outputs. Reviewer alone owns review-only actions and final result.

## Code Review Result

- Overall Verdict: FAIL
- Dimension Assessment:
  - Correctness: Fail — post-dispatch validation and unsupported-path rejection can leave the exact Node run active.
  - Completeness: Fail — API-1 does not cover every rejection after provider dispatch ownership has transferred to Edge.
  - Test Coverage: Fail — the required regression set does not exercise rejected normalized/tunnel results or assert exact cancellation for those paths.
  - API Contract: Fail — a rejected dispatched run is closed locally without the Edge-Node `CANCEL_RUN` handoff.
  - Code Quality: Pass — the typed disposition and active-generation controller are otherwise cohesive and race-safe under the exercised paths.
  - Implementation Deviation: Fail — the claimed exact active-stage cancellation boundary excludes rejection before controller registration.
  - Verification Trust: Pass — all reported commands reproduced with exit status 0; the defect is an uncovered path rather than contradictory output.
  - Spec Conformance: Fail — SDD S13 requires failure paths to terminate without hidden provider work.
- Findings:
  - Required — `apps/edge/internal/openai/hot_path_dispatch.go:52`, `apps/edge/internal/openai/hot_path_dispatch.go:115`, `apps/edge/internal/openai/hot_path_dispatch.go:1209`, `apps/edge/internal/openai/hot_path_dispatch.go:1221`: after `SubmitProviderPool` has returned an owned normalized/tunnel handle, unsupported execution paths and dispatch-evidence validation failures either call only `Close()` or return without closing. No exact `CancelRun(CANCEL_RUN)` is sent, so the Node-side run can continue after Edge has rejected it. Centralize post-dispatch rejection ownership so it sends one cancel using `DispatchInfo` and closes every returned handle, use it for selector and downstream normalized/tunnel rejection variants, preserve `validation_error`, and add table-driven exact-target/count/close assertions for every variant.
- Routing Signals:
  - `review_rework_count=1`
  - `evidence_integrity_failure=false`
- Next Step: Invoke the plan skill in `prepare-follow-up` mode with this raw finding and fresh verification evidence; route and validate the smallest exact-cancellation repair before archiving this pair.
