<!-- task=m-iop-owned-single-request-agent-execution/02+01_preset_binding plan=4 tag=REVIEW_REVIEW_API milestone-task=preset-binding -->

# Review Follow-up: Exact Fixed-Light Shape Rejection

## For the Implementing Agent

Do not start until the packet 01 dependency command passes. Implement this plan exactly within the listed write boundary, run every verification command, fill all implementation-owned sections of `CODE_REVIEW-cloud-G05.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 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`.

## Archive Evidence Snapshot

- Superseded pair: `plan_cloud_G07_3.log`, `code_review_cloud_G07_3.log`.
- Archived verdict: FAIL with Required R2 and no Suggested or Nit findings. R2 covers extra route keys admitted by the fixed-light validator and duplicate stage-role orderings misclassified as generic inconsistency.
- Every planned dependency, formatting, focused, package, race, vet, full Edge, and diff-hygiene command passed freshly. Focused reviewer reproducers still proved that a valid light route plus an extra route compiles and that `work,work,review` / `plan,review,review` do not return the typed duplicate error.
- Split predecessor 01 remains satisfied by `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/01_preset_config/complete.log`.

## Finding Resolution Map

| Finding | Mode | Exact Fix / Dependency Evidence | Changed or Satisfied Precondition |
|---------|------|---------------------------------|-----------------------------------|
| Required R2 | direct-fix | Require the marked preset route map to contain only `light`, detect every duplicate role before positional role/model/options validation in `single_request_preset_binding.go`, and add typed unit plus managed resolver/model-list regressions in `single_request_preset_binding_test.go` and `principal_routes_test.go`. | The previously untested extra-route and non-leading duplicate-role inputs now change from admitted/misclassified results to deterministic fail-closed results. |

## Background

The prior follow-up closed the real resolver fallback, option preservation, and nested-copy defects, but its defense-in-depth validator still accepts one inconsistent route-map variant and misclassifies two duplicate-role orderings. This packet completes the existing fixed-light admission invariant without changing config schema, public API, service DTOs, or coordinator execution.

## Analysis

### Files Read

- `agent-task/m-iop-owned-single-request-agent-execution/02+01_preset_binding/plan_cloud_G07_3.log`
- `agent-task/m-iop-owned-single-request-agent-execution/02+01_preset_binding/code_review_cloud_G07_3.log`
- `agent-task/m-iop-owned-single-request-agent-execution/02+01_preset_binding/code_review_cloud_G07_2.log`
- `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/01_preset_config/complete.log`
- `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-contract/outer/anthropic-compatible-api.md`
- `agent-contract/inner/edge-config-runtime-refresh.md`
- `agent-spec/input/openai-compatible-surface.md`
- `agent-spec/runtime/provider-pool-config-refresh.md`
- `packages/go/config/execution_preset_types.go`
- `apps/edge/internal/openai/single_request_preset_binding.go`
- `apps/edge/internal/openai/single_request_preset_binding_test.go`
- `apps/edge/internal/openai/principal_routes.go`
- `apps/edge/internal/openai/principal_routes_test.go`
- `apps/edge/internal/openai/route_resolution.go`
- `apps/edge/internal/openai/openai_auth_routes_models_test.go`
- `apps/edge/internal/service/single_request_types.go`
- `apps/edge/internal/service/single_request_types_test.go`

### 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: `preset-binding`; targeted Acceptance Scenario: S02.
- S02 and its Evidence Map require immutable fixed-light preset decode/authorization, model echo, workspace snapshot, refresh isolation, and fail-closed dynamic/inconsistent binding rejection. This follow-up narrows the checklist to exact route-map cardinality and duplicate-role classification while retaining managed resolver/model-list verification.

### Verification Context

- No separate verification handoff was supplied. Repository-native evidence came from the active review output, focused source inspection, the approved SDD, current contract/spec documents, and deterministic local tests.
- The current checkout uses `/config/.local/bin/go` (`go1.26.2 linux/arm64`) from `/config/workspace/iop-s0`. No credential, external provider, remote runner, Node workspace, coordinator, or SSE lifecycle is required for this bounded admission-validation packet.
- Fresh reviewer execution passed the dependency check, formatting, focused service/OpenAI tests, package tests, race detector, `go vet ./apps/edge/...`, `go test ./apps/edge/... -count=1`, and `git diff --check`.
- Focused temporary reviewer tests (removed after execution) failed deterministically: an extra route returned no error, and duplicate `work`/`review` sequences returned `errSingleRequestBindingInconsistent` instead of `errSingleRequestBindingDuplicate`.
- Precondition: the unique archived packet 01 `complete.log` above. Constraint: preserve all already-green R1/R3 production and deep-copy behavior. Confidence is high because both residual branches are isolated in one pure validator.

### Test Coverage Gaps

- `TestSingleRequestPresetBindingRejectsInvalidDefenseInDepth` covers only a duplicate `plan` at the second position; it does not cover duplicate roles whose first mismatch occurs before the duplicate is discovered.
- No test supplies a valid `light` route together with an extra route key and requires admission to fail.
- Managed production coverage proves other invalid shapes are omitted from model discovery and rejected by resolution, but it does not include these two residual variants.

### Symbol References

- None. No symbol is renamed or removed.

### Split Judgment

- Keep one compact plan. Route-map cardinality, duplicate-first classification, typed unit assertions, and production no-fallback assertions are one pure fixed-shape validation invariant.
- The dependent directory `02+01_preset_binding` still names predecessor index 01, satisfied by `agent-task/archive/2026/08/m-iop-owned-single-request-agent-execution/01_preset_config/complete.log`.

### Scope Rationale

- Modify only the admission validator, its focused unit tests, the existing managed resolver/model-list invalid-shape table, and the active review evidence file.
- Do not change config loading/validation, resolver behavior, service bindings/deep copy, contracts, specs, coordinator execution, workspace runtime, Node wire, HTTP envelopes, or SSE behavior; those paths are already conformant or belong to later Milestone packets.

### Final Routing

- `evaluation_mode=isolated-reassessment`; `finalizer=finalize-task-policy.sh`; `finalizer_mode=pair`; status routed with no missing evidence, blocker, or capability gap.
- Build closures: scope/context/verification/evidence/ownership/decision all true. Scores 1/0/1/2/1 = G05; base `local-fit`, final `recovery-boundary` because `review_rework_count=2` and `evidence_integrity_failure=true`; route `worker/cloud/G05`; canonical filename `PLAN-cloud-G05.md`.
- Build signals: `large_indivisible_context=false`; positive loop risks `boundary_contract`, `structured_interpretation`, and `variant_product` (3); risk boundary false; recovery boundary true.
- Review closures: scope/context/verification/evidence/ownership/decision all true. Scores 1/0/1/2/1 = G05; route `official-review`, catalog `review/cloud/G05`; canonical filename `CODE_REVIEW-cloud-G05.md`.

## Dependencies and Execution Order

1. Verify the unique packet 01 completion evidence.
2. Enforce exact route-map cardinality and duplicate-first role classification.
3. Add focused typed-error and managed production no-fallback regressions.
4. Run every fresh verification command.

## Implementation Checklist

- [ ] Reject every extra route key and classify every duplicate fixed-stage role with `errSingleRequestBindingDuplicate` before positional validation.
- [ ] Add focused typed-error and managed resolver/model-list regression cases for the extra-route and duplicate-role variants.
- [ ] Run the dependency, formatting, focused, package, race, vet, full Edge regression, and diff-hygiene verification commands exactly as written.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Implementation Plan

### [REVIEW_REVIEW_API-1] Close the exact fixed-light shape boundary

**Problem**

- `apps/edge/internal/openai/single_request_preset_binding.go:116` reads the `light` route but never rejects additional route keys, so a crafted marked preset with a valid light route plus an extra route still compiles.
- `apps/edge/internal/openai/single_request_preset_binding.go:131` discovers duplicates inside the same loop that checks expected positional roles. For `work,work,review` and `plan,review,review`, positional inconsistency returns before the duplicate is observed, contrary to the typed error contract.

**Solution**

Before (`apps/edge/internal/openai/single_request_preset_binding.go:116`):

```go
route, ok := preset.Routes[config.ModeLight]
if !ok {
    return errSingleRequestBindingMissingStage
}
// ...
seenRoles := make(map[string]struct{}, len(route.Stages))
for i, want := range expected {
    st := route.Stages[i]
    if _, dup := seenRoles[st.Role]; dup {
        return errSingleRequestBindingDuplicate
    }
    seenRoles[st.Role] = struct{}{}
    if st.Role != want.role {
        return errSingleRequestBindingInconsistent
    }
```

After:

```go
if len(preset.Routes) != 1 {
    return errSingleRequestBindingInconsistent
}
route, ok := preset.Routes[config.ModeLight]
if !ok {
    return errSingleRequestBindingMissingStage
}
// ...
seenRoles := make(map[string]struct{}, len(route.Stages))
for _, stage := range route.Stages {
    if _, dup := seenRoles[stage.Role]; dup {
        return errSingleRequestBindingDuplicate
    }
    seenRoles[stage.Role] = struct{}{}
}
for i, want := range expected {
    st := route.Stages[i]
    if st.Role != want.role {
        return errSingleRequestBindingInconsistent
    }
```

Keep the existing missing-stage, dynamic-model, option-inconsistent, authorization, valid managed admission, R1 resolver no-fallback, and R3 deep-copy behavior unchanged.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/openai/single_request_preset_binding.go` — require the single `light` route and perform duplicate detection before positional checks.
- [ ] `apps/edge/internal/openai/single_request_preset_binding_test.go` — table-test duplicate plan/work/review variants and the extra-route rejection with exact typed errors.
- [ ] `apps/edge/internal/openai/principal_routes_test.go` — add the residual invalid shapes to managed resolver/model-list fail-closed coverage.

**Test Strategy**

- Extend `TestSingleRequestPresetBindingRejectsInvalidDefenseInDepth` with table-driven duplicate sequences covering plan, work, and review duplicates; every case must return `errSingleRequestBindingDuplicate`.
- Add a valid-light-plus-extra-route case requiring `errSingleRequestBindingInconsistent`.
- Extend `TestManagedSingleRequestPresetFailsClosed` with extra-route and non-leading duplicate variants so `/v1/models` omits the virtual model and `resolveRouteDispatchForPrincipal` returns `ErrRouteNotFound` through the real production boundary.

**Verification**

- `go test ./apps/edge/internal/openai -run 'Test(SingleRequestPresetBindingRejectsInvalidDefenseInDepth|ManagedSingleRequestPresetFailsClosed)' -count=1`
- Expected: every duplicate ordering has the duplicate error, every extra-route marked preset fails closed, and managed discovery/resolution omit/reject both variants.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/openai/single_request_preset_binding.go` | REVIEW_REVIEW_API-1 |
| `apps/edge/internal/openai/single_request_preset_binding_test.go` | REVIEW_REVIEW_API-1 |
| `apps/edge/internal/openai/principal_routes_test.go` | REVIEW_REVIEW_API-1 |
| `agent-task/m-iop-owned-single-request-agent-execution/02+01_preset_binding/CODE_REVIEW-cloud-G05.md` | REVIEW_REVIEW_API-1 |

## Final Verification

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/01_preset_config/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/01_preset_config/complete.log' | wc -l)" -eq 1`
   - Expected: exactly one active or archived predecessor `complete.log` satisfies index 01.
2. `test -z "$(gofmt -l apps/edge/internal/openai/single_request_preset_binding.go apps/edge/internal/openai/single_request_preset_binding_test.go apps/edge/internal/openai/principal_routes_test.go)"`
   - Expected: no path output; all changed Go files are formatted.
3. `go test ./apps/edge/internal/openai -run 'Test(SingleRequestPresetBindingRejectsInvalidDefenseInDepth|ManagedSingleRequestPresetFailsClosed)' -count=1`
   - Expected: exact fixed-light shape, typed duplicate classification, and managed production no-fallback regressions pass freshly.
4. `go test ./apps/edge/internal/service ./apps/edge/internal/openai -count=1`
   - Expected: both binding and OpenAI packages pass without cached results.
5. `go test -race -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service`
   - Expected: both packages pass under the race detector.
6. `go vet ./apps/edge/...`
   - Expected: no diagnostics.
7. `go test ./apps/edge/... -count=1`
   - Expected: the full Edge profile passes without cached results.
8. `git diff --check`
   - Expected: no whitespace errors.

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