<!-- task=m-iop-hot-path-one-shot-execution/07+02,04,06_route_selector_direct plan=2 tag=REVIEW_API milestone-task=route-selector,direct-flow -->

# Direct Preset and Exact Metadata Closure

## For the Implementing Agent

Implement every checklist item, run the exact verification commands, and fill the implementation-owned sections in `CODE_REVIEW-*-G??.md` with actual notes and stdout/stderr. Keep the active pair in place and report ready for official review. If blocked, record only 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 production selector/direct path now runs for presets that declare workspace operations, but a valid direct-only preset without `workspace_tools` still bypasses it and leaves coordinator state active. Reserved-path matching also accepts substring paths, and tunnel collection promotes IOP run/frame metadata into public provider response fields. This follow-up closes those remaining S03/S07 boundaries without expanding into light execution.

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-iop-hot-path-one-shot-execution/07+02,04,06_route_selector_direct/plan_cloud_G10_1.log`.
- Prior review: `agent-task/m-iop-hot-path-one-shot-execution/07+02,04,06_route_selector_direct/code_review_cloud_G10_1.log`.
- Verdict: FAIL with 3 Required, 0 Suggested, and 0 Nit findings.
- Required closure: activate direct-only presets without workspace tools; compare the complete mapped control path with the issued path; keep IOP run/frame correlation separate from provider response ID/timestamp.
- Affected files: hot-path activation/collection, structural path classification, and focused handler/classifier tests.
- Verification evidence: all planned focused, race, full Edge, vet, formatting, and diff commands passed, but reviewer probes left a direct-only request `active`, admitted `prefix/.iop/job/<request_id>/plan.md` as `light_exact_pair`, and emitted `run-pool-tunnel` as the public ID for a provider body with no ID.
- Roadmap carryover: `route-selector,direct-flow`; SDD S03 requires exact structural controls and S07 requires real direct completion with no reserved artifact path.

## Dependencies and Execution Order

- `02+01_preset_generation` is satisfied by `agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/02+01_preset_generation/complete.log`.
- `04+02,03_preset_model_authorization` is satisfied by `agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/04+02,03_preset_model_authorization/complete.log`.
- `06+04,05_request_identity_ingress` is satisfied by `agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/06+04,05_request_identity_ingress/complete.log`.

## Analysis

### Files Read

- `apps/edge/internal/openai/chat_handler.go`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/hot_path_dispatch.go`
- `apps/edge/internal/openai/hot_path_selector.go`
- `apps/edge/internal/openai/hot_path_direct.go`
- `apps/edge/internal/openai/hot_path_selector_test.go`
- `apps/edge/internal/openai/hot_path_direct_test.go`
- `apps/edge/internal/openai/request_identity_ingress.go`
- `apps/edge/internal/openai/request_identity_handler_test.go`
- `apps/edge/internal/openai/route_resolution.go`
- `apps/edge/internal/openai/anthropic_native.go`
- `apps/edge/internal/openai/anthropic_stream.go`
- `apps/edge/internal/openai/provider_test_support_test.go`
- `packages/go/config/execution_preset_types.go`
- `packages/go/config/execution_preset_config_test.go`
- `agent-contract/outer/openai-compatible-api.md`
- `agent-contract/outer/anthropic-compatible-api.md`
- `agent-spec/input/openai-compatible-surface.md`

### SDD Criteria

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-hot-path-one-shot-execution/SDD.md`; status `[승인됨]`, lock released.
- First-line tasks: `route-selector,direct-flow`.
- S03/Evidence Map requires exact structural output-shape, allowlist, and hard-gate table evidence without natural-language parsing.
- S07/Evidence Map requires handler-integrated direct text/high-thinking/tool completion with no `.iop/job/<request_id>` artifact path.
- The checklist therefore adds direct-only handler terminal coverage, whole-argument reserved-path rejection, and provider-versus-transport metadata boundary tests before rerunning the common race/full-package evidence.

### Verification Context

- No verification handoff was supplied. Repository-native evidence came from the active pair, Edge/testing domain rules, local Edge smoke profile, approved SDD, API contracts, current source, and focused tests.
- Host preflight: repository root `/config/workspace/iop-s0`; Go `/config/.local/bin/go`, version `go1.26.2 linux/arm64`; dirty shared worktree is the intended checkout.
- Fresh reviewer commands passed: focused hot-path tests, focused race tests, the common race suite, full `./apps/edge/...`, `go vet ./apps/edge/...`, `gofmt -d`, and `git diff --check`.
- Focused reviewer probes used existing fake handler fixtures and proved three uncovered failures: direct-only coordinator state remained `active`; a prefixed plan path classified as `light_exact_pair`; and a missing provider ID returned HTTP 200 with the IOP run ID.
- External live-provider smoke is not required here; S16 `hot-smoke` owns credentialed Claude/Pi qualification. Confidence: high.

### Test Coverage Gaps

- `TestHotPathPresetHandlersDirect` covers direct execution only when the preset has workspace-tool alternatives; it does not cover valid direct-only/no-workspace presets for either protocol.
- `TestHotPathSelectorDecisionMatrix` covers a different issued path and multiple reserved values, but not a mapped argument that contains the issued path as a substring or absolute/prefixed/suffixed variants.
- Handler tests always supply provider response IDs and do not prove that IOP run IDs or frame timestamps remain internal when provider metadata is absent.

### Symbol References

- No rename or removal is planned.
- `presetHotPathEnabled` is called by `chat_handler.go` and `anthropic_handler.go`.
- `mappedControlPath` is called only by `classifyReservedControlCall`.
- `collectPresetTunnelResult` is called only by `collectPresetSelectorResult`.

### Split Judgment

Keep one plan. Preset activation, exact structural classification, and public response identity are one selector-to-direct acceptance boundary; splitting them would permit a successful handler route that still misclassifies controls or emits transport metadata as provider metadata.

### Scope Rationale

Include only direct preset activation, exact reserved-path comparison, provider response metadata separation, and required regressions. Exclude light workspace binding/pair execution, local/review/repair, cleanup, cross-stage envelope composition, observability, config/schema changes, contracts, and credentialed smoke because later Milestone children own those boundaries and no contract text change is needed for this bug fix.

### Final Routing

- `evaluation_mode=isolated-reassessment`; `finalizer=finalize-task-policy.sh`, mode `pair`.
- Build and review closures are true: scope, context, verification, evidence, ownership, and decisions are fixed; capability gap: none.
- Build scores `(2,1,2,2,1)` => G08, base basis `local-fit`, final basis `recovery-boundary`, cloud, `PLAN-cloud-G08.md`.
- Review scores `(2,1,2,2,1)` => G08, `official-review`, cloud, `CODE_REVIEW-cloud-G08.md` using Codex `gpt-5.6-sol` xhigh.
- `large_indivisible_context=false`; risks `temporal_state,boundary_contract,structured_interpretation,variant_product` (4); `review_rework_count=2`; `evidence_integrity_failure=true`; risk and recovery boundaries matched.

## Implementation Checklist

- [ ] Route valid direct-only presets without workspace tools through production structural selection and exactly-once direct terminal handling for Chat and Messages.
- [ ] Require the complete normalized mapped control path to equal the exact issued job/plan/review path and reject substring, absolute, suffixed, and multi-source variants.
- [ ] Preserve only provider-reported public response identity/timing on tunnel direct output, keep IOP run/frame metadata internal, and fail missing required provider identity through endpoint-standard errors.
- [ ] Add the focused regressions and run fresh focused, race, full Edge, vet, formatting, deterministic reference, and diff verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_API-1] Activate direct-only presets

#### Problem

`apps/edge/internal/openai/hot_path_dispatch.go:31-33` requires `len(dispatch.Preset.WorkspaceTools) > 0` before either handler collects and classifies selector output. Valid direct-only presets intentionally omit workspace tools, so ingress creates and activates coordinator state, ordinary provider relay returns HTTP 200, and the logical request never enters the direct terminal transition.

#### Solution

Make production hot-path eligibility depend on an admitted preset and selector binding, not on plan-bearing workspace operations. Let the classifier reject any reserved control when no canonical operation exists, while direct output continues through the direct runner.

```go
// Before
return dispatch.IsPreset && selector != "" && len(dispatch.Preset.WorkspaceTools) > 0

// After
return dispatch.IsPreset && selector != ""
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/hot_path_dispatch.go` — remove the workspace-tools gate from direct production activation.
- [ ] `apps/edge/internal/openai/hot_path_direct_test.go` — add Chat and Messages direct-only/no-workspace handler cases with terminal exactly-once assertions.

#### Test Strategy

Extend `TestHotPathPresetHandlersDirect` with direct-only presets that have an empty `WorkspaceTools` slice. Exercise both protocols and assert provider selection uses the selector model, the virtual model is echoed, the response is successful, and coordinator state is terminal with a rejected second terminal.

#### Verification

```bash
go test -count=1 ./apps/edge/internal/openai -run 'TestHotPathPresetHandlersDirect'
```

Expected: PASS; both direct-only protocols use the selector/direct path and close exactly once.

### [REVIEW_API-2] Enforce exact issued control paths

#### Problem

`apps/edge/internal/openai/hot_path_selector.go:242-267` reduces a mapped argument to the first `.iop/job` substring. A value such as `prefix/.iop/job/<request_id>/plan.md` therefore equals the extracted issued path and can complete an otherwise exact light pair even though the actual tool argument targets a different path.

#### Solution

Normalize and compare the complete mapped path argument. Preserve the independent recursive scan across all structured/raw arguments so conflicting or additional reserved occurrences still fail before mode selection.

```go
// Before
paths := reservedPathsFromString(text)
return paths[0], len(paths) == 1

// After
mappedPath := cleanRelativePath(text)
return mappedPath, mappedPath != "" && mappedPath != "."
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/hot_path_selector.go` — compare the whole mapped value to exact issued paths without substring promotion.
- [ ] `apps/edge/internal/openai/hot_path_selector_test.go` — add prefixed, absolute, suffixed, same-path-extra-source, and conflicting-path table rows.

#### Test Strategy

Expand `TestHotPathSelectorDecisionMatrix` so every non-exact mapped path returns a deterministic malformed reason. Retain positive exact prepare and pair rows and prose-independence coverage.

#### Verification

```bash
go test -count=1 ./apps/edge/internal/openai -run 'TestHotPathSelectorDecisionMatrix'
```

Expected: PASS; only complete exact mapped arguments produce prepare/plan/review controls.

### [REVIEW_API-3] Separate provider metadata from transport correlation

#### Problem

`apps/edge/internal/openai/hot_path_dispatch.go:251-255` fills missing decoded response ID and creation time from the selected IOP run ID and tunnel-frame timestamp. The direct encoder then exposes those internal values as provider response metadata, so a malformed provider response can become a synthetic successful OpenAI response.

#### Solution

Keep selected run ID and frame timestamps only in dispatch/gate correlation. Require protocol-required provider response identity, and OpenAI creation time where the public shape requires it, from decoded provider JSON/SSE; return a sanitized collection error before any caller bytes are committed when required metadata is missing. Preserve normalized RunEvent identity separately because that path is IOP-owned rather than provider-tunnel passthrough.

```go
// Before
if stage.ResponseID == "" { stage.ResponseID = responseID }
if stage.Created == 0 { stage.Created = created }

// After
if err := validateProviderStageMetadata(protocol, stage); err != nil { return normalizedStageOutput{}, err }
// selected.RunID and frame.Timestamp remain internal correlation only.
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/hot_path_dispatch.go` — remove run/frame promotion and validate decoded tunnel provider metadata.
- [ ] `apps/edge/internal/openai/hot_path_direct_test.go` — add JSON/SSE missing-ID and frame-metadata isolation cases while retaining positive provider ID/usage assertions.

#### Test Strategy

Extend `TestHotPathPresetHandlersDirect` with provider bodies/streams whose ID is absent and frames whose run ID/timestamp are distinct. Assert endpoint-standard failure before response commit and verify positive cases retain the provider ID/created values and virtual model echo.

#### Verification

```bash
go test -count=1 ./apps/edge/internal/openai -run 'TestHotPathPresetHandlersDirect'
```

Expected: PASS; transport correlation never becomes public provider identity/timing.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/edge/internal/openai/hot_path_dispatch.go` | REVIEW_API-1, REVIEW_API-3 |
| `apps/edge/internal/openai/hot_path_selector.go` | REVIEW_API-2 |
| `apps/edge/internal/openai/hot_path_selector_test.go` | REVIEW_API-2 |
| `apps/edge/internal/openai/hot_path_direct_test.go` | REVIEW_API-1, REVIEW_API-3 |
| `agent-task/m-iop-hot-path-one-shot-execution/07+02,04,06_route_selector_direct/CODE_REVIEW-cloud-G08.md` | REVIEW_API-1, REVIEW_API-2, REVIEW_API-3 |

## Final Verification

```bash
test -f agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/02+01_preset_generation/complete.log
test -f agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/04+02,03_preset_model_authorization/complete.log
test -f agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/06+04,05_request_identity_ingress/complete.log
rg --sort path -n 'presetHotPathEnabled|mappedControlPath|collectPresetTunnelResult|classifyHotPathOutput' apps/edge/internal/openai --glob '*.go'
go test -count=1 ./apps/edge/internal/openai -run 'TestHotPath(SelectorDecisionMatrix|PresetHandlersDirect|Direct)'
go test -race -count=1 ./apps/edge/internal/openai -run 'TestHotPath(Selector|PresetHandlers|Direct)'
go test -race -count=1 ./packages/go/streamgate ./packages/go/config ./apps/edge/internal/openai ./apps/edge/internal/service
route_selector_followup_tmp_dir="$(mktemp -d /config/.tmp-iop-route-selector-followup.XXXXXX)"
TMPDIR="$route_selector_followup_tmp_dir" go test -count=1 ./apps/edge/...
rmdir "$route_selector_followup_tmp_dir"
go vet ./apps/edge/...
gofmt -d apps/edge/internal/openai/hot_path_dispatch.go apps/edge/internal/openai/hot_path_selector.go apps/edge/internal/openai/hot_path_selector_test.go apps/edge/internal/openai/hot_path_direct_test.go
git diff --check
```

Expected: all commands exit 0; direct-only presets terminal exactly once, only exact complete reserved paths classify as controls, provider tunnel identity/timing is never synthesized from IOP transport metadata, and no direct response emits `.iop/job/`. Cached test output is not acceptable.

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