<!-- task=m-iop-owned-single-request-agent-execution/23+22_error_cancel plan=3 tag=REVIEW_API milestone-task=error-cancel -->

# Correct terminal ownership and request-budget classification

## For the Implementing Agent

Filling the implementation-owned sections of `CODE_REVIEW-cloud-G10.md` is the mandatory final implementation step. Execute this plan's fixed root causes, files, and verification commands; paste actual notes and stdout/stderr, keep both active files in place, and report ready for review. Finalization belongs only to the code-review skill. If blocked, record the exact blocker, attempted commands/output, and resume condition 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`.

## Background

The first S11 implementation review found three closed-terminal classification defects: live-context provider cancellation was treated as caller disconnect, generic upstream HTTP 400 was treated as a context limit, and request wall-clock exhaustion was treated as a timeout. The follow-up keeps service, executor, provider-stage, and buffered/SSE behavior atomic so one owner produces one contract-correct terminal without fallback, partial success, or another ingress.

## Archive Evidence Snapshot

- The failed implementation pair is archived as `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/plan_cloud_G10_2.log` and `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_2.log`; the review verdict is `FAIL` with Required R1, R2, and R3, `review_rework_count=1`, and `evidence_integrity_failure=true`.
- R1 affects `apps/edge/internal/openai/single_request_quality_gate.go` and `apps/edge/internal/openai/single_request_executor.go`: live `context.Background()` plus raw `context.Canceled` produced `cancelled` instead of a provider/internal error, so buffered/SSE could suppress a real failure.
- R2 affects `apps/edge/internal/openai/single_request_provider_stage.go`: a generic upstream `RESPONSE_START` with status 400 produced `error/context` instead of `error/provider`, conflicting with the outer contract's `api_error` rule for upstream 400.
- R3 affects `apps/edge/internal/service/single_request.go` and the executor parent-context handoff: a real `WallClockMS=10` expiry produced `error/timeout` instead of `error/budget`, and a provider-stage return can race the service terminal owner after the parent request context expires.
- Fresh reviewer verification passed focused/full race suites, `go vet`, Edge package tests, the approved SDD common suite, deterministic searches, and `git diff --check`. Focused review reproducers contradicted the submitted complete-matrix claim. Temporary reproducer files were removed after recording the outcomes in the archived review.
- Task 22 remains satisfied by exactly `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/22+21_executor_activation/complete.log`. The S11 `error-cancel` milestone/SDD mapping and no-proto/no-second-ingress boundary remain unchanged.

## Finding Resolution Map

| Finding | Mode | Exact fix/dependency evidence | Changed or satisfied precondition |
|---------|------|-------------------------------|-----------------------------------|
| Required R1 | direct-fix | Change cancellation ownership in `apps/edge/internal/openai/single_request_quality_gate.go` and the fallback/parent-context handoff in `apps/edge/internal/openai/single_request_executor.go`; add unit plus buffered/SSE regressions in `apps/edge/internal/openai/single_request_quality_gate_test.go`, `apps/edge/internal/openai/single_request_executor_test.go`, `apps/edge/internal/openai/single_request_handler_test.go`, and `apps/edge/internal/openai/single_request_anthropic_stream_test.go`. | A raw `context.Canceled` with a live request context becomes provider/internal failure; only an authoritatively cancelled parent context or owned service cancellation sentinel becomes `cancelled`.
| Required R2 | direct-fix | Change response-start status handling in `apps/edge/internal/openai/single_request_provider_stage.go` and add the 400/413/5xx classification matrix in `apps/edge/internal/openai/single_request_quality_gate_test.go`. | Generic HTTP 400 and 5xx remain `error/provider`; deterministic HTTP 413 remains `error/context`.
| Required R3 | direct-fix | Change both request-deadline terminal paths in `apps/edge/internal/service/single_request.go`, defer expired parent-context terminal ownership in `apps/edge/internal/openai/single_request_executor.go`, and add service/composite race regressions in `apps/edge/internal/service/single_request_test.go` and `apps/edge/internal/openai/single_request_executor_test.go`. | Actual request wall-clock exhaustion deterministically emits one `error/budget`; an independently expired stage/provider deadline still emits `error/timeout`.

## 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/testing/rules.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/finalize-task-routing/SKILL.md`
- `agent-ops/skills/common/plan/templates/review-stub-template.md`
- `agent-test/local/rules.md`
- `agent-test/local/edge-smoke.md`
- `agent-roadmap/current.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`
- `agent-spec/index.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-spec/input/openai-compatible-surface.md`
- `agent-contract/index.md`
- `agent-contract/outer/anthropic-compatible-api.md`
- `apps/edge/internal/openai/single_request_quality_gate.go`
- `apps/edge/internal/openai/single_request_quality_gate_test.go`
- `apps/edge/internal/openai/single_request_provider_stage.go`
- `apps/edge/internal/openai/single_request_executor.go`
- `apps/edge/internal/openai/single_request_executor_test.go`
- `apps/edge/internal/openai/single_request_handler_test.go`
- `apps/edge/internal/openai/single_request_anthropic_stream_test.go`
- `apps/edge/internal/service/single_request.go`
- `apps/edge/internal/service/single_request_test.go`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/PLAN-cloud-G10.md`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/CODE_REVIEW-cloud-G10.md`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/plan_cloud_G10_0.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/plan_cloud_G10_1.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_0.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_1.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/verification-6-protobuf.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/verification-7-contract-spec.log`
- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/verification-8-terminal-symbols.log`
- `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/22+21_executor_activation/complete.log`

### SDD Criteria

- Approved and unlocked SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`; first-line `milestone-task=error-cancel` maps to Acceptance Scenario S11.
- S11 requires stage/request budget exhaustion, repetition/no-progress, malformed calls, provider/tool timeout, output/context limit, and disconnect to converge without another Claude request, implicit fallback, or partial success.
- Evidence Map row S11 requires a budget/error/cancel/length/repetition terminal matrix. R1 restores disconnect ownership, R2 restores provider/context error separation, and R3 restores request-budget separation; the implementation checklist and fresh race commands below exercise those rows through service, composite, buffered, and SSE paths.

### Verification Context

- No external handoff was supplied. Repository-native evidence consists of the failed review, source/contract/SDD files, local test rules, existing terminal matrices, and fresh reviewer commands.
- Reviewer reproduction outcomes: live-context `providerFailure(..., context.Canceled, ...)` returned `{Kind:cancelled ErrorClass:}`; upstream response-start status 400 returned `{Kind:error ErrorClass:context}`; actual request wall-clock expiry returned `{Kind:error ErrorClass:timeout}`.
- Fresh reviewer commands passed: focused race tests, service compatibility race tests, `go vet`, `go test ./apps/edge/... -count=1`, the approved SDD common race suite, deterministic searches, and `git diff --check`. `make proto` reproduced inherited generated bytes with SHA-256 `5c9d6c580ecf9c9fba857787b5d2757757d7289b267b44074bf6c2108b4cc1a9`; the existing task-17 protobuf diff is outside this packet.
- Preconditions: task 22 has one archived completion log; branch is `feature/iop-owned-single-request-agent-execution`; the milestone worktree is intentionally dirty with predecessor and sibling work, so the implementer must preserve unrelated changes.
- Constraints: no retry, fallback, second ingress, partial success, public raw error, new metric label, contract vocabulary, spec vocabulary, or protobuf change. S12 external Claude qualification remains a separate task and is not required for this deterministic S11 follow-up.
- Cached Go test output is not accepted; every test command uses `-count=1`, and concurrency-sensitive commands use `-race`.
- Confidence is high because each Required finding has a direct failing case and a closed production owner/fix boundary.

### Test Coverage Gaps

- Existing cancellation tests cover an already-cancelled caller context, but not raw provider/service `context.Canceled` while the request context is live or the resulting buffered/SSE projection.
- Existing provider codec tests cover finish-reason context limits, but not response-start HTTP status ownership; status 400 and 413 are currently conflated.
- Existing service tests carry synthetic budget dispositions but do not expire the immutable request wall-clock context or exercise the monitor/executor race.
- Existing composite tests cover stage timeout and cancellation independently but do not prove that parent request expiry is owned by the service and cannot be won by a stage timeout envelope.

### Symbol References

- No public symbol is renamed or removed.
- Behavioral call sites under change are `singleRequestQualityGate.providerFailure`, `singleRequestQualityGate.serviceFailure`, `submitSingleRequestClosedTerminal`, `collectProviderStageFrames`, the request monitor in `startSingleRequestWithToolLoopObserved`, and `singleRequestHandle.finalizeExecutorReturn`.
- Buffered and SSE terminal serializers are unchanged consumers; their tests must prove the corrected provider disposition is emitted rather than silently suppressed.

### Split Judgment

- Keep one plan. The indivisible invariant is that one parent-context owner and one closed disposition must agree across service request timing, composite stage handoff, provider response classification, and both Anthropic projectors. Splitting would leave an intermediate build that can still select the wrong terminal winner or public error shape.
- The existing `23+22_error_cancel` dependency remains satisfied by the exact task-22 completion log cited above; no new dependency is introduced.

### Scope Rationale

- Include only the service request-deadline classification, executor parent-context handoff/fallback, provider cancellation/status classification, and direct regression tests.
- Exclude production buffered/SSE projector changes because their shared policy already maps `error/provider`, `error/context`, `error/budget`, and `cancelled` correctly; only end-to-end regressions are needed.
- Exclude outer contract and current spec edits because they already state the expected mapping and S11 invariant. Exclude protobuf/Edge-Node wire, generic StreamGate, retry/reselection, metrics, S12 Claude execution, deployment, and roadmap mutation.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer `finalize-task-policy.sh`, mode `pair`.
- Build closures are all true: scope, context, verification, evidence, ownership, and decision. Scores are `2/2/2/2/2` => G10; base/final route basis is `grade-boundary`, lane `cloud`, catalog `worker/cloud/G10`, canonical `PLAN-cloud-G10.md`.
- Review closures are all true. Scores are `2/2/2/2/2` => G10; route basis `official-review`, lane `cloud`, catalog `review/cloud/G10`, canonical `CODE_REVIEW-cloud-G10.md`.
- `large_indivisible_context=false`; positive loop risks are `temporal_state`, `concurrent_consistency`, `boundary_contract`, and `variant_product` (4). `review_rework_count=1`; `evidence_integrity_failure=true`. Risk and recovery boundaries match, while the grade-boundary basis remains authoritative. No capability gap exists.

## Implementation Checklist

- [ ] Make cancellation classification context-authoritative in the quality gate and composite fallback, then prove live-context provider/service cancellation is an error while real caller disconnect remains silent.
- [ ] Separate generic upstream HTTP 400/5xx provider failures from deterministic HTTP 413 context-limit evidence and add the response-start status matrix.
- [ ] Make the service the sole parent request-context terminal owner, classify request wall-clock expiry as budget across monitor/executor races, and preserve independent stage/provider timeout classification.
- [ ] Run focused race, compatibility, full Edge/SDD, protobuf reproducibility, deterministic contract/symbol, and diff-hygiene verification freshly.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_API-1] Make cancellation ownership context-authoritative

**Problem**

`apps/edge/internal/openai/single_request_quality_gate.go:72` and line 116 use a comma-separated switch case that accepts either a cancelled context or raw `context.Canceled`. `apps/edge/internal/openai/single_request_executor.go:122` repeats the raw-error fallback. With a live request context, a provider/internal raw cancellation is therefore converted to caller-owned `cancelled` and suppressed by the Anthropic surface.

**Solution**

Only a cancelled authoritative request/stage context may produce provider-path `cancelled`; `ErrSingleRequestCancelled` remains the explicit service-owned cancellation sentinel. A raw `context.Canceled` with a live context falls through to `error/provider` or `error/internal_tool`. If the composite parent context is already done, return its error without submitting a competing envelope so the service resolves caller cancellation versus request budget.

Before (`apps/edge/internal/openai/single_request_quality_gate.go:71-75`):

```go
switch {
case ctx != nil && errors.Is(ctx.Err(), context.Canceled), errors.Is(err, context.Canceled):
	return g.failure(edgeservice.SingleRequestTerminalCancelled, "", cause)
```

After:

```go
switch {
case ctx != nil && errors.Is(ctx.Err(), context.Canceled):
	return g.failure(edgeservice.SingleRequestTerminalCancelled, "", cause)
// A raw context.Canceled with a live context is not caller-owned.
```

**Modified Files and Checklist**

- [ ] Update provider/service classification in `apps/edge/internal/openai/single_request_quality_gate.go`.
- [ ] Update parent-context and untyped fallback ownership in `apps/edge/internal/openai/single_request_executor.go`.
- [ ] Add live/cancelled context unit rows in `apps/edge/internal/openai/single_request_quality_gate_test.go` and executor ownership coverage in `apps/edge/internal/openai/single_request_executor_test.go`.
- [ ] Add actual buffered and SSE provider-cancellation regressions in `apps/edge/internal/openai/single_request_handler_test.go` and `apps/edge/internal/openai/single_request_anthropic_stream_test.go`.

**Test Strategy**

Add `TestSingleRequestQualityGateCancellationOwnership` for provider/service live versus cancelled contexts, `TestSingleRequestExecutorParentContextOwnership`, `TestAnthropicSingleRequestLiveContextProviderCancellationBuffered`, and `TestSingleRequestAnthropicStreamLiveContextProviderCancellation`. Use a provider mock returning raw `context.Canceled` while the caller context stays live; assert one provider-class `api_error`, one ingress, no success terminal, no second dispatch, and no raw error. Retain the existing real caller-cancel rows and silent-disconnect assertions.

**Verification**

Run the focused command in Final Verification 2; all cancellation ownership rows pass under `-race` with fresh execution.

### [REVIEW_API-2] Keep generic upstream HTTP errors in provider class

**Problem**

`apps/edge/internal/openai/single_request_provider_stage.go:138-140` classifies both HTTP 400 and 413 as `errProviderStageContextLimit`. The outer contract at lines 127-128 and 423-426 reserves `invalid_request_error` for caller/context failures and requires upstream 400/502 failures to become sanitized `api_error`.

**Solution**

Treat only deterministic response-start context-limit evidence available at this boundary—HTTP 413—as `errProviderStageContextLimit`. All other non-2xx response-start statuses, including generic 400 and 5xx, remain `errProviderStageGeneric`; existing explicit provider finish reasons continue to classify context/output limits after body decoding.

Before (`apps/edge/internal/openai/single_request_provider_stage.go:138-142`):

```go
if frame.GetStatusCode() == http.StatusBadRequest || frame.GetStatusCode() == http.StatusRequestEntityTooLarge {
	return nil, errors.Join(errProviderStageGeneric, errProviderStageContextLimit)
}
if frame.GetStatusCode() < 200 || frame.GetStatusCode() >= 300 {
	return nil, errProviderStageGeneric
}
```

After:

```go
if frame.GetStatusCode() == http.StatusRequestEntityTooLarge {
	return nil, errors.Join(errProviderStageGeneric, errProviderStageContextLimit)
}
if frame.GetStatusCode() < 200 || frame.GetStatusCode() >= 300 {
	return nil, errProviderStageGeneric
}
```

**Modified Files and Checklist**

- [ ] Correct response-start status classification in `apps/edge/internal/openai/single_request_provider_stage.go`.
- [ ] Add 400/413/5xx closed-disposition rows in `apps/edge/internal/openai/single_request_quality_gate_test.go`.

**Test Strategy**

Add `TestSingleRequestQualityGateProviderHTTPStatusClassification` with deterministic frame channels for status 400, 413, and 502. Assert 400/502 become `error/provider`, 413 becomes `error/context`, each produces exactly one closed terminal, and no body/private value is retained.

**Verification**

Run the focused command in Final Verification 2; every response-start status row passes freshly.

### [REVIEW_API-3] Make request wall-clock expiry a service-owned budget terminal

**Problem**

`apps/edge/internal/service/single_request.go:293` and line 772 pass `singleRequestErrorClassTimeout` when the immutable request execution context reaches its wall-clock deadline. The composite can also race that owner by submitting a typed stage timeout after its parent context expires. This makes request-budget outcome nondeterministic and violates the S11 budget/timeout distinction.

**Solution**

Use `singleRequestErrorClassInternalToolBudget` for the service-owned request deadline in both monitor and executor-return paths. In `submitSingleRequestClosedTerminal`, when the composite parent context is done, return its error without submitting a stage terminal; the service then distinguishes caller context cancellation from its own wall-clock deadline. Keep provider stage deadlines whose parent is live as `error/timeout`.

Before (`apps/edge/internal/service/single_request.go:290-294`):

```go
if ctx.Err() != nil {
	h.cancelLocked()
} else if errors.Is(execCtx.Err(), context.DeadlineExceeded) {
	h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassTimeout)
}
```

After:

```go
if ctx.Err() != nil {
	h.cancelLocked()
} else if errors.Is(execCtx.Err(), context.DeadlineExceeded) {
	h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassInternalToolBudget)
}
```

**Modified Files and Checklist**

- [ ] Correct monitor and executor-return request-budget classes in `apps/edge/internal/service/single_request.go`.
- [ ] Prevent parent-context terminal envelope competition in `apps/edge/internal/openai/single_request_executor.go`.
- [ ] Add actual wall-clock terminal/race coverage in `apps/edge/internal/service/single_request_test.go`.
- [ ] Add composite request-budget/no-later-dispatch/no-waiter coverage while retaining stage-timeout coverage in `apps/edge/internal/openai/single_request_executor_test.go`.

**Test Strategy**

Add `TestSingleRequestRequestWallClockBudgetDisposition` with a short wall clock and executor blocked on its context; loop enough iterations under `-race` to cover monitor/executor ordering and assert one `error/budget`, one closed progress terminal, returned budget sentinel, and no retained execution. Add `TestSingleRequestExecutorRequestBudgetOwnership` with a provider blocked until the parent expires; assert one provider dispatch, zero tool calls/later stage dispatches, zero bridge waiters, and one budget terminal. Preserve an explicit shorter stage-timeout row that still expects `error/timeout`.

**Verification**

Run the focused command in Final Verification 2 and the compatibility matrix in Final Verification 3; budget and timeout ownership remain distinct under `-race`.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/edge/internal/openai/single_request_quality_gate.go` | REVIEW_API-1 |
| `apps/edge/internal/openai/single_request_provider_stage.go` | REVIEW_API-2 |
| `apps/edge/internal/openai/single_request_executor.go` | REVIEW_API-1, REVIEW_API-3 |
| `apps/edge/internal/openai/single_request_quality_gate_test.go` | REVIEW_API-1, REVIEW_API-2 |
| `apps/edge/internal/openai/single_request_executor_test.go` | REVIEW_API-1, REVIEW_API-3 |
| `apps/edge/internal/openai/single_request_handler_test.go` | REVIEW_API-1 |
| `apps/edge/internal/openai/single_request_anthropic_stream_test.go` | REVIEW_API-1 |
| `apps/edge/internal/service/single_request.go` | REVIEW_API-3 |
| `apps/edge/internal/service/single_request_test.go` | REVIEW_API-3 |
| `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/CODE_REVIEW-cloud-G10.md` | REVIEW_API-1, REVIEW_API-2, REVIEW_API-3 evidence |

## Final Verification

1. Confirm the failed review and predecessor dependency are the exact expected evidence:

```sh
test -f agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_2.log && test -f agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/22+21_executor_activation/complete.log && rg -n 'Overall Verdict: FAIL|Required R1|Required R2|Required R3|review_rework_count=1|evidence_integrity_failure=true' agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_2.log
```

Expected: both files exist and the archived review prints every listed verdict/finding/routing line.

2. Run every new ownership/classification regression freshly under the race detector:

```sh
go test -race ./apps/edge/internal/service ./apps/edge/internal/openai -run 'Test(SingleRequestRequestWallClockBudgetDisposition|SingleRequestQualityGateCancellationOwnership|SingleRequestQualityGateProviderHTTPStatusClassification|SingleRequestExecutorParentContextOwnership|SingleRequestExecutorRequestBudgetOwnership|AnthropicSingleRequestLiveContextProviderCancellationBuffered|SingleRequestAnthropicStreamLiveContextProviderCancellation)$' -count=1
```

Expected: both packages pass; live-context raw cancellation is provider/internal error, 400/413/5xx separate correctly, request budget is deterministic, and caller cancellation stays silent.

3. Rerun the complete S11 focused and service compatibility matrices:

```sh
go test -race ./apps/edge/internal/service ./apps/edge/internal/openai -run 'Test(SingleRequestTerminalDisposition|SingleRequestQualityGate|SingleRequestExecutor(Cancellation|StageFailures|TerminalWaiterCleanup)|AnthropicSingleRequestErrorCancelMatrix|SingleRequestAnthropicStreamTerminalDisposition)' -count=1
```

Expected: all existing and new terminal, timeout, budget, cancel, no-progress, and projector rows pass without cached output.

4. Run Edge static and package regressions:

```sh
go vet ./apps/edge/internal/service ./apps/edge/internal/openai && go test ./apps/edge/... -count=1
```

Expected: vet and every Edge package test pass.

5. Run the approved SDD common race suite:

```sh
go test -race -count=1 ./packages/go/config ./packages/go/streamgate ./apps/edge/internal/openai ./apps/edge/internal/service ./apps/node/internal/node ./apps/node/internal/transport ./apps/node/internal/workspace
```

Expected: every package passes freshly under `-race`.

6. Prove inherited protobuf output remains byte-for-byte reproducible without requiring the predecessor diff to be clean relative to `HEAD`:

```sh
b_before=$(sha256sum proto/gen/iop/runtime.pb.go) && make proto && b_after=$(sha256sum proto/gen/iop/runtime.pb.go) && test "$b_before" = "$b_after" && printf '%s\n' "$b_after"
```

Expected: generation succeeds and prints the unchanged generated-file hash.

7. Confirm the living contract/spec policy and corrected production symbols deterministically:

```sh
rg --sort path -n 'upstream error \(400/502\)|every other `error/\*`|caller disconnect|request wall-clock|error-cancel|S11' agent-contract/outer/anthropic-compatible-api.md agent-spec/runtime/edge-node-execution.md agent-spec/input/openai-compatible-surface.md && rg --sort path -n 'providerFailure|serviceFailure|submitSingleRequestClosedTerminal|StatusRequestEntityTooLarge|singleRequestErrorClassInternalToolBudget' apps/edge/internal/openai apps/edge/internal/service --glob '*.go'
```

Expected: searches exit 0 and show the existing contract/spec rules plus every corrected owner and regression call site.

8. Check diff hygiene:

```sh
git diff --check
```

Expected: no output and exit 0.

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