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

# Code Review Reference - REVIEW_API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> Execute the plan's selected root cause, scope, files, and dependency decisions as written. Do not choose another owner, narrow/expand the write boundary, or replace a fix with another verification attempt.
> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## Overview

date=2026-08-07
task=m-iop-owned-single-request-agent-execution/23+22_error_cancel, plan=4, tag=REVIEW_API

## Archive Evidence Snapshot

- `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_3.log` ended in `FAIL` with Required R1: child `DeadlineExceeded` paths in `single_request_tool_loop.go` and `single_request_artifact.go` can override request wall-clock ownership.
- Fresh review verification passed the submitted focused, compatibility, full Edge, and SDD race suites, but a separate race-enabled reproduction over 2,000 real internal-tool wall-clock expiries produced 67–99 `error/timeout` terminals per 200-request run. The passing submitted suite therefore does not cover the failing child path.
- The provider-cancellation, upstream HTTP-status, and executor/monitor request-budget corrections from `plan_cloud_G10_3.log` remain satisfied and are regression-only scope here.
- `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/22+21_executor_activation/complete.log` satisfies predecessor subtask 22. Milestone S12 external Claude smoke remains the separate `claude-smoke` task and is not a substitute for S11 deterministic coverage.

## For the Review Agent

> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section.

Compare implementation of each item against source files and verify that output in `Verification Results` matches code.
Review completion means the following steps are finished:

1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals.
2. Archive `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_4.log` and `PLAN-cloud-G10.md` → `plan_cloud_G10_4.log`.
3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-iop-owned-single-request-agent-execution/23+22_error_cancel/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill.
4. If PASS and task group is `m-iop-owned-single-request-agent-execution`, preserve the first-line `milestone-task` metadata in `complete.log` and report it for the runtime aggregation event. Roadmap state evaluation belongs to `sync-milestone-workstate`.
5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting.

---

## Implementation Item Completion

| Item | Status |
|------|---------|
| REVIEW_API-1 — Make child operation deadlines request-authoritative | [x] |

## Implementation Checklist

- [x] Add one service-owned parent-first child-operation classifier and route internal-tool and artifact failure/observation paths through it without changing genuine earlier-stage timeout behavior.
- [x] Add repeated race-enabled real internal-tool and artifact request-wall-clock regressions that assert budget, raw-free observation, and exactly one terminal.
- [x] Run focused race, compatibility, full Edge/SDD, protobuf reproducibility, deterministic contract/symbol, and diff-hygiene verification freshly.
- [x] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Review-Only Checklist

> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent.
> Implementing agents must not modify or check this section.

- [x] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`.
- [x] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match.
- [x] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G10_4.log`.
- [x] Archive active `PLAN-*-G??.md` to `plan_cloud_G10_4.log`.
- [x] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`.
- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
- [ ] If PASS, move active task directory `agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/` to `agent-task/archive/YYYY/MM/m-iop-owned-single-request-agent-execution/23+22_error_cancel/` and update this checklist at the final archive path.
- [ ] If PASS and task group is `m-<milestone-slug>`, preserve and report `milestone-task` metadata for runtime aggregation, without modifying roadmap or directly calling `update-roadmap`.
- [ ] If PASS for split work, remove empty active parent `agent-task/m-iop-owned-single-request-agent-execution/` or verify it was kept due to remaining siblings/files.
- [x] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.

## Deviations from Plan

- None. The shared helper is named `classifyChildOperationContext`, so the planned deterministic symbol search remains unchanged.
- Superseded implementation diagnostics caught two compatibility details before the final fresh suite: an artifact request-budget race initially retained the artifact-local sentinel, and a cleanup cancellation initially changed an already-expired stage tool observation to `cancel`. The final implementation uses the request-owned budget sentinel and preserves a genuinely earlier child deadline as timeout. A first compatibility-matrix run also caught the typed Node timeout sentinel; the final implementation preserves `ErrSingleRequestInternalToolFailed` for a live-parent typed timeout while context-derived timeouts retain their existing budget sentinel.

## Key Design Decisions

- `singleRequestHandle.classifyChildOperationContext` is the only child context ordering source. It checks authoritative caller cancellation, immutable request deadline/`execCtx`, reached child deadline, child cancellation, and finally a typed fallback.
- Tool failure and tool observation consume the same classification result, preventing a single operation from publishing different terminal and observation classes at a deadline boundary.
- Artifact request wall-clock expiry uses the same service-owned `ErrSingleRequestInternalToolBudget` sentinel as the monitor, so monitor-versus-artifact scheduling cannot change the returned sentinel. Artifact-local stage/size timeout behavior remains distinct.
- Typed Node timeout responses retain `ErrSingleRequestInternalToolFailed` with public `error/timeout`; inherited context expiry retains the established budget sentinel. No terminal enum, metric label, wire type, retry, fallback, or ingress behavior changed.

## Reviewer Checkpoints

- Confirm one service-owned classifier checks caller cancellation before request wall-clock budget and request budget before child/stage deadline.
- Confirm both internal-tool terminal failure and tool observation use that ordering; request expiry must not leave a timeout observation even if the tool goroutine wins the race.
- Confirm artifact read/write failure uses the same ordering and does not retain a separate child-first deadline branch.
- Confirm real tool and artifact regressions repeatedly exercise inherited parent expiry, assert one public `error/budget` terminal and `internal_tool_budget` observation, and fail on any timeout outcome.
- Confirm an earlier stage deadline while the request parent remains live is still `error/timeout` and caller cancellation remains cancellation.
- Confirm no OpenAI projector, public terminal vocabulary, metric label, contract/spec, protobuf, Node wire, retry/fallback, or second-ingress behavior changed.

## Verification Results

Paste actual stdout/stderr for every command. If output is too long, record the exact command and saved output path; summaries are insufficient.

### 1. Failed review and predecessor evidence

Command:

```sh
test -f agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_3.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|review_rework_count=2|evidence_integrity_failure=true' agent-task/m-iop-owned-single-request-agent-execution/23+22_error_cancel/code_review_cloud_G10_3.log
```

Output:

```text
22:- 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`.
106: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
112:284:- Overall Verdict: FAIL
113:295:  - Required R1 — `apps/edge/internal/openai/single_request_quality_gate.go:72`, `apps/edge/internal/openai/single_request_quality_gate.go:116`, and the fallback at `apps/edge/internal/openai/single_request_executor.go:122` classify any raw `context.Canceled` error as caller cancellation even when the supplied request context is still live. A focused call to `providerFailure(context.Background(), context.Canceled, ...)` produced `{Kind:cancelled ErrorClass:}` instead of the required provider failure, which can silently suppress a real provider/internal error at the Anthropic surface. Classify cancellation only from an authoritatively cancelled request/stage context or an owned service cancellation sentinel; keep a raw `context.Canceled` from a live context in the provider/internal error class, and add buffered/SSE regression coverage proving it is not silently dropped.
117:300:  - `evidence_integrity_failure=true`
118:301:- Next Step: Prepare and implement a `REVIEW_API` follow-up plan for Required R1, R2, and R3; do not write `complete.log`.
360:- Overall Verdict: FAIL
371:  - Required R1 — `apps/edge/internal/service/single_request_tool_loop.go:233-260` and `apps/edge/internal/service/single_request_artifact.go:196-208` classify a child operation context's `DeadlineExceeded` as `timeout` before checking the service-owned `execCtx` and immutable request deadline. A fresh race-enabled reproduction across 2,000 actual internal-tool request wall-clock expiries produced 67–99 `error/timeout` terminals per 200-request run, with only the remainder reaching `error/budget`. This violates SDD S11 and the submitted R3 ownership claim. Route tool and artifact failures through a service-owned classifier that prioritizes caller cancellation and request wall-clock exhaustion, preserves `timeout` only for a genuinely earlier child/stage deadline, and add real internal-tool and artifact request-wall-clock race regressions.
373:  - `review_rework_count=2`
374:  - `evidence_integrity_failure=true`
375:- Next Step: Prepare and implement a `REVIEW_API` follow-up plan for Required R1; do not write `complete.log`.
```

### 2. Repeated real child-path request-budget ownership

Command:

```sh
go test -race ./apps/edge/internal/service -run '^TestSingleRequest(InternalTool|Artifact)RequestWallClockBudgetOwnership$' -count=10
```

Output:

```text
ok  	iop/apps/edge/internal/service	13.656s
```

### 3. Parent request budget and earlier stage timeout controls

Command:

```sh
go test -race ./apps/edge/internal/service -run '^TestSingleRequest(RequestWallClockBudgetDisposition|InternalToolLoopStageDeadline|ObservationDeadlineClassifications)$' -count=10
```

Output:

```text
ok  	iop/apps/edge/internal/service	8.229s
```

### 4. Complete S11 and prior ownership compatibility matrices

Command:

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

Output:

```text
ok  	iop/apps/edge/internal/service	1.047s
ok  	iop/apps/edge/internal/openai	1.378s
```

### 5. Edge vet and package regressions

Command:

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

Output:

```text
ok  	iop/apps/edge/cmd/edge	0.198s
ok  	iop/apps/edge/internal/authprojection	0.040s
ok  	iop/apps/edge/internal/bootstrap	0.538s
ok  	iop/apps/edge/internal/configrefresh	0.116s
ok  	iop/apps/edge/internal/controlplane	6.618s
ok  	iop/apps/edge/internal/edgecmd	0.109s
ok  	iop/apps/edge/internal/edgevalidate	0.069s
ok  	iop/apps/edge/internal/events	0.048s
ok  	iop/apps/edge/internal/input	0.109s
ok  	iop/apps/edge/internal/input/a2a	0.086s
ok  	iop/apps/edge/internal/node	0.072s
ok  	iop/apps/edge/internal/openai	8.425s
ok  	iop/apps/edge/internal/opsconsole	0.040s
ok  	iop/apps/edge/internal/service	8.236s
ok  	iop/apps/edge/internal/transport	4.774s
```

### 6. Approved SDD common race suite

Command:

```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
```

Output:

```text
ok  	iop/packages/go/config	1.824s
ok  	iop/packages/go/streamgate	1.972s
ok  	iop/apps/edge/internal/openai	12.455s
ok  	iop/apps/edge/internal/service	9.294s
ok  	iop/apps/node/internal/node	3.581s
ok  	iop/apps/node/internal/transport	6.601s
ok  	iop/apps/node/internal/workspace	5.873s
```

### 7. Protobuf reproducibility

Command:

```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"
```

Output:

```text
protoc \
	--go_out=. \
	--go_opt=module=iop \
	--proto_path=. \
	proto/iop/runtime.proto \
	proto/iop/node.proto \
	proto/iop/control.proto \
	proto/iop/job.proto
5c9d6c580ecf9c9fba857787b5d2757757d7289b267b44074bf6c2108b4cc1a9  proto/gen/iop/runtime.pb.go
```

### 8. Contract/spec and parent-first classifier searches

Command:

```sh
rg --sort path -n '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 'classifyChildOperation|requestDeadline|singleRequestErrorClassInternalToolBudget|SingleRequestTerminalErrorBudget|SingleRequestTerminalErrorTimeout' apps/edge/internal/service --glob '*.go'
```

Output:

```text
agent-contract/outer/anthropic-compatible-api.md:129:| `cancelled` | no response body after caller disconnect | no later event after caller disconnect |
agent-contract/outer/anthropic-compatible-api.md:138:completion only and cannot write a second terminal. This is the implemented S11
agent-contract/outer/anthropic-compatible-api.md:139:`error-cancel` boundary; external Claude qualification remains deferred to S12.
agent-contract/outer/anthropic-compatible-api.md:189:iteration/output/deadline or request wall-clock budgets fail closed without
agent-contract/outer/anthropic-compatible-api.md:394:6. on caller disconnect, silent cancellation with no later event.
agent-spec/runtime/edge-node-execution.md:104:    notes: Request-local S11 stage classification and fixed-hash repetition/no-progress detection
agent-spec/runtime/edge-node-execution.md:107:    notes: S11 provider, timeout, budget, malformed, context, length, cancel, tool, and no-progress terminal evidence
agent-spec/runtime/edge-node-execution.md:206:| single-request S11 terminal policy | One validated, copy-safe terminal disposition is frozen across envelope/result/progress with kinds `end_turn`, `length`, `error`, and `cancelled`. Error classes are `provider`, `validation`, `timeout`, `budget`, `repetition`, `malformed`, `context`, `internal_tool`, and `workspace_cleanup`. Cleanup can replace a pending success/length before publication; no acknowledgement race can publish a second terminal. |
agent-spec/runtime/edge-node-execution.md:211:| internal workspace tool loop | The service decodes only `workspace_read`, `workspace_list`, `workspace_write`, `workspace_delete`, and `workspace_command`, opens the admitted workspace once, dispatches one call at a time on the frozen generation, and delivers one deep-copied typed result to the emitting executor continuation. Unique request/stage/tool correlation, per-stage iteration/output/deadline limits, request wall-clock budget, and typed cancel fail closed without external continuation or reselection. |
agent-spec/runtime/edge-node-execution.md:236:- The service freezes the first public terminal candidate. Legacy successful results normalize to `end_turn`; output limits produce `length`; caller disconnect produces silent `cancelled`; validation/context become `invalid_request_error`; other errors become `api_error`. Buffered and SSE projectors share that policy, emit at most one terminal, and never expose private partial stage content for `length`. This completes deterministic S11 `error-cancel` evidence without changing the Edge-Node protobuf wire. S12 external Claude/Mac qualification remains pending.
agent-spec/runtime/edge-node-execution.md:329:- `go test -race ./apps/edge/internal/service ./apps/edge/internal/openai -run 'Test(SingleRequestTerminalDisposition|SingleRequestQualityGate|AnthropicSingleRequestErrorCancelMatrix|SingleRequestAnthropicStreamTerminalDisposition)' -count=1` — deterministic S11 error-cancel/length matrix, first-terminal ownership, one ingress, no second request, disconnect silence, and raw-free output evidence.
agent-spec/runtime/edge-node-execution.md:341:- The composite single-request executor is installed at Edge input startup (`apps/edge/internal/input/manager.go`), wiring the active Plan -> Work -> Review stage pipeline for single-request execution. Private stage outcomes use the implemented closed S11 terminal policy and stop without retry/fallback or a second request. Deterministic local activation and terminal evidence are proven, while actual external Claude qualification remains explicitly deferred to S12 (`claude-smoke`).
agent-spec/runtime/edge-node-execution.md:346:- 2026-08-07: Implemented the S11 `error-cancel` boundary: one frozen service terminal disposition, request-local typed stage classification, fixed-hash repetition/no-progress detection, shared buffered/SSE Anthropic mapping, silent disconnect cancellation, private-partial suppression for `max_tokens`, and deterministic one-ingress/one-terminal/no-second-request evidence. The Edge-Node protobuf wire is unchanged and S12 remains pending.
agent-spec/input/openai-compatible-surface.md:143:    notes: Request-local S11 stage classification and fixed-hash repetition/no-progress detection
agent-spec/input/openai-compatible-surface.md:146:    notes: S11 timeout, budget, repetition, malformed, context, length, cancel, and tool terminal evidence
agent-spec/input/openai-compatible-surface.md:167:| marked single-request S11 terminal policy | The service freezes one closed `end_turn`, `length`, `error`, or `cancelled` disposition. `error` classes are provider, validation, timeout, budget, repetition, malformed, context, internal-tool, and workspace-cleanup. Buffered and SSE share one projection: `end_turn`; `max_tokens` with no private partial output; `400 invalid_request_error` for validation/context; `502 api_error` for other failures; and silent cancellation after caller disconnect. No terminal classification retries, falls back, opens a second request, or later writes success. |
agent-spec/input/openai-compatible-surface.md:169:| marked internal workspace tool loop | The service accepts only closed read/list/write/delete/command calls from the saved internal stage, opens the admitted Node workspace once, executes calls sequentially on the frozen connection generation, correlates one result to one unique request/stage/tool identity, and resumes only through the emitting executor's optional continuation. Strict decoding, capability checks, cumulative per-stage iteration/output/deadline limits, request wall-clock budget, and typed cancellation fail closed without fallback or another Messages request. |
agent-spec/input/openai-compatible-surface.md:257:- A marked single-request Messages dispatch requires the narrow service coordinator capability and never falls back to the generic provider pool. The handler copies the immutable binding and request input and counts the accepted HTTP admission once with no labels. The service projects exactly one frozen terminal candidate through both response modes: buffered/SSE `end_turn`; buffered/SSE `max_tokens` without private partial content; `invalid_request_error` for validation/context; `api_error` for provider, timeout, budget, repetition, malformed, internal-tool, and workspace-cleanup failures; or silent cancellation after caller disconnect. The streaming path maps only fixed plan/work/review/repair summaries, serializes pings and monotonic text-block indices with one terminal owner, stops and joins liveness before terminal/return, and acknowledges completion only after `message_stop`. Arbitrary progress, reasoning, tool/provider/credential/workspace data, raw failures, and internal stage terminals stay private. No classified terminal triggers retry, fallback, partial success, a second request, or a later success terminal. Count-tokens does not enter or increment this path.
agent-spec/input/openai-compatible-surface.md:315:- The marked single-request SSE projector and private workspace continuation do not add event kinds, filters, release rules, or recovery behavior to the generic Stream Evidence Gate. The active Plan -> Work -> Review composite and request-artifact cleanup use the closed S11 `error-cancel`/length policy with deterministic local evidence. S11 is implemented; only actual external Claude qualification remains explicitly deferred to S12 (`claude-smoke`).
agent-spec/input/openai-compatible-surface.md:320:- 2026-08-07: Implemented and documented S11 `error-cancel`: one closed service terminal disposition, request-local typed failure/no-progress classification, shared buffered/SSE `end_turn`/`max_tokens`/`invalid_request_error`/`api_error` mapping, silent disconnect, private-partial suppression, and deterministic one-ingress/one-terminal/no-second-request evidence. S12 external qualification remains pending.
apps/edge/internal/service/single_request.go:67:	SingleRequestTerminalErrorTimeout          SingleRequestTerminalErrorClass = "timeout"
apps/edge/internal/service/single_request.go:68:	SingleRequestTerminalErrorBudget           SingleRequestTerminalErrorClass = "budget"
apps/edge/internal/service/single_request.go:95:			SingleRequestTerminalErrorTimeout, SingleRequestTerminalErrorBudget,
apps/edge/internal/service/single_request.go:181:	requestDeadline time.Time
apps/edge/internal/service/single_request.go:249:	requestDeadline, _ := execCtx.Deadline()
apps/edge/internal/service/single_request.go:264:		requestDeadline: requestDeadline,
apps/edge/internal/service/single_request.go:293:					h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassInternalToolBudget)
apps/edge/internal/service/single_request.go:442:	if !h.requestDeadline.IsZero() && !h.toolLoop.stageDeadline.IsZero() && !h.toolLoop.stageDeadline.Before(h.requestDeadline) {
apps/edge/internal/service/single_request.go:675:	deadline := h.requestDeadline
apps/edge/internal/service/single_request.go:779:			!h.requestDeadline.IsZero() && !time.Now().Before(h.requestDeadline) {
apps/edge/internal/service/single_request.go:780:			h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassInternalToolBudget)
apps/edge/internal/service/single_request.go:793:// classifyChildOperationContext applies the request-owned cancellation and
apps/edge/internal/service/single_request.go:797:func (h *singleRequestHandle) classifyChildOperationContext(ctx context.Context, fallback singleRequestErrorClass) (singleRequestOutcome, singleRequestErrorClass) {
apps/edge/internal/service/single_request.go:803:		!h.requestDeadline.IsZero() && !now.Before(h.requestDeadline):
apps/edge/internal/service/single_request.go:804:		return singleRequestOutcomeError, singleRequestErrorClassInternalToolBudget
apps/edge/internal/service/single_request.go:1013:		return singleRequestErrorClassInternalToolBudget
apps/edge/internal/service/single_request.go:1038:		errorClass = SingleRequestTerminalErrorTimeout
apps/edge/internal/service/single_request.go:1039:	case observed == singleRequestErrorClassInternalToolBudget:
apps/edge/internal/service/single_request.go:1040:		errorClass = SingleRequestTerminalErrorBudget
apps/edge/internal/service/single_request.go:1046:		errorClass = SingleRequestTerminalErrorBudget
apps/edge/internal/service/single_request.go:1052:		errorClass = SingleRequestTerminalErrorTimeout
apps/edge/internal/service/single_request.go:1069:	case SingleRequestTerminalErrorTimeout:
apps/edge/internal/service/single_request.go:1071:	case SingleRequestTerminalErrorBudget, SingleRequestTerminalErrorRepetition:
apps/edge/internal/service/single_request.go:1072:		return singleRequestErrorClassInternalToolBudget
apps/edge/internal/service/single_request_artifact.go:201:	outcome, errorClass := h.classifyChildOperationContext(ctx, fallback)
apps/edge/internal/service/single_request_artifact.go:211:	if errorClass == singleRequestErrorClassInternalToolBudget {
apps/edge/internal/service/single_request_artifact.go:212:		h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassInternalToolBudget)
apps/edge/internal/service/single_request_observation.go:67:	singleRequestErrorClassInternalToolBudget singleRequestErrorClass = "internal_tool_budget"
apps/edge/internal/service/single_request_observation.go:152:		singleRequestErrorClassInternalToolBudget, singleRequestErrorClassInternalToolFailed,
apps/edge/internal/service/single_request_observation.go:201:		singleRequestErrorClassInternalToolBudget, singleRequestErrorClassInternalToolFailed,
apps/edge/internal/service/single_request_observation_test.go:1137:		if terminal := terminalEvent(t, observer); terminal.ErrorClass != singleRequestErrorClassInternalToolBudget {
apps/edge/internal/service/single_request_observation_test.go:1254:		if terminal := terminalEvent(t, observer); terminal.ErrorClass != singleRequestErrorClassInternalToolBudget {
apps/edge/internal/service/single_request_observation_test.go:1305:		{name: "budget", err: fmt.Errorf("wrapped: %w", ErrSingleRequestInternalToolBudget), want: singleRequestErrorClassInternalToolBudget},
apps/edge/internal/service/single_request_test.go:446:		want := SingleRequestTerminalDisposition{Kind: SingleRequestTerminalError, ErrorClass: SingleRequestTerminalErrorBudget}
apps/edge/internal/service/single_request_test.go:562:		{name: "timeout", stage: SingleRequestStateFailed, terminal: SingleRequestTerminalDisposition{Kind: SingleRequestTerminalError, ErrorClass: SingleRequestTerminalErrorTimeout}},
apps/edge/internal/service/single_request_test.go:563:		{name: "budget", stage: SingleRequestStateFailed, terminal: SingleRequestTerminalDisposition{Kind: SingleRequestTerminalError, ErrorClass: SingleRequestTerminalErrorBudget}},
apps/edge/internal/service/single_request_tool_loop.go:168:		outcome, errorClass = h.classifyChildOperationContext(ctx, singleRequestErrorClassInternalToolFailed)
apps/edge/internal/service/single_request_tool_loop.go:195:		outcome, errorClass = h.classifyChildOperationContext(ctx, singleRequestErrorClassInternalToolFailed)
apps/edge/internal/service/single_request_tool_loop.go:209:		outcome, errorClass = singleRequestOutcomeError, singleRequestErrorClassInternalToolBudget
apps/edge/internal/service/single_request_tool_loop.go:235:	outcome, errorClass := h.classifyChildOperationContext(ctx, fallback)
apps/edge/internal/service/single_request_tool_loop.go:244:	case errorClass == singleRequestErrorClassInternalToolBudget:
apps/edge/internal/service/single_request_tool_loop.go:245:		h.failLockedWithErrorClass(ErrSingleRequestInternalToolBudget, singleRequestErrorClassInternalToolBudget)
apps/edge/internal/service/single_request_tool_loop_test.go:250:	wantTerminal := SingleRequestTerminalDisposition{Kind: SingleRequestTerminalError, ErrorClass: SingleRequestTerminalErrorBudget}
apps/edge/internal/service/single_request_tool_loop_test.go:274:			if event.Outcome != singleRequestOutcomeError || event.ErrorClass != singleRequestErrorClassInternalToolBudget {
```

### 9. Diff hygiene

Command:

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

Output:

```text
[no stdout or stderr; exit status 0]
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## Section Ownership

| Section | Owner | Note |
|---------|-------|------|
| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section |
| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content |
| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan |
| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry |
| Code Review Result | Review agent appends | Not included in stub |

## Code Review Result

- Overall Verdict: FAIL
- Dimension Assessment:
  - Correctness: Fail
  - Completeness: Fail
  - Test coverage: Fail
  - API contract: Fail
  - Code quality: Pass
  - Implementation deviation: Fail
  - Verification trust: Fail
  - Spec conformance: Fail
- Findings:
  - Required R1 — `apps/edge/internal/service/single_request_tool_loop.go:77-82` still classifies an expired stage deadline as `timeout` without first checking the immutable request deadline. Because `apps/edge/internal/service/single_request.go:442-444` stops the stage timer when its deadline is not earlier than the request deadline but retains that later stage deadline, a tool call admitted after both deadlines can beat the request monitor and freeze `error/timeout` even though the request wall clock expired first. A fresh focused reproducer set `requestDeadline` one millisecond before `stageDeadline` and received `error class = "timeout", want "internal_tool_budget"`; this contradicts SDD S11 and the plan's request-authoritative acceptance criterion despite all submitted suites passing. Route tool-call admission deadline failure through the same parent-first request/child classifier (or perform the identical request-first ordering while holding the handle lock), and add a deterministic admission-race regression proving request budget wins while the existing genuinely-earlier-stage admission control remains timeout.
- Routing Signals:
  - `review_rework_count=3`
  - `evidence_integrity_failure=true`
- Next Step: Prepare and implement a `REVIEW_API` follow-up plan for Required R1; do not write `complete.log`.
