<!-- task=m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator plan=2 tag=REVIEW_API milestone-task=request-identity -->

# Harden Logical Request Lineage and Frontier Bounds

## For the Implementing Agent

Implement the two review fixes, run every command, and fill the implementation-owned sections in `CODE_REVIEW-cloud-G08.md` with actual notes and output. Keep the active files in place and report ready for review; finalization is code-review-skill only. 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 first coordinator implementation passed its planned tests, but fresh review reproducers found that lossy Chat decoding can collapse distinct tool schemas to one fingerprint and that a frontier can accept a non-bijective provider call mapping. The store also lacks per-request mapping bounds and admits requests without the preset generation that the Hot Path contract requires to remain pinned.

## Archive Evidence Snapshot

- Closing pair: `agent-task/m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator/plan_cloud_G07_1.log` and `agent-task/m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator/code_review_cloud_G08_1.log`; verdict `FAIL`.
- Required findings: preserve lossless canonical Chat/Anthropic lineage; reject duplicate and replayed public/provider tool IDs; bound each frontier and request mapping set; require a non-empty preset generation.
- Fresh evidence: the planned focused/race/vet/diff commands passed, but reviewer-only reproducers failed because JSON Schema maxima `9007199254740992` and `9007199254740993` hashed identically and two public IDs mapped to one provider ID without error. The temporary reproducers were removed after capture.
- Dependencies: `agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/02+01_preset_generation/complete.log` and `agent-task/archive/2026/08/m-iop-hot-path-one-shot-execution/04+02,03_preset_model_authorization/complete.log` are the exact completed predecessors.
- Roadmap carryover: `milestone-task=request-identity`; SDD scenario S05 and its Evidence Map remain the acceptance source.

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

## Analysis

### Files Read

- `apps/edge/internal/openai/request_coordinator.go`
- `apps/edge/internal/openai/request_lineage.go`
- `apps/edge/internal/openai/request_coordinator_test.go`
- `apps/edge/internal/openai/server.go`
- `apps/edge/internal/openai/chat_types.go`
- `apps/edge/internal/openai/anthropic_types.go`
- `agent-task/m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator/PLAN-cloud-G07.md`
- `agent-task/m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator/CODE_REVIEW-cloud-G08.md`

### SDD Criteria

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-hot-path-one-shot-execution/SDD.md`; status `[승인됨]`, lock released.
- Milestone metadata: `milestone-task=request-identity`; Acceptance Scenario S05.
- Evidence Map S05 requires full-history/frontier evidence, lineage and tool-schema mutation rejection, bijective public/provider tool-ID mapping, cross-principal/missing-state rejection, and concurrency race safety.
- These requirements drive lossless raw JSON fingerprinting, collision/replay/bounds checks before mutation, and the focused plus race verification below.

### Verification Context

- No external handoff was supplied. Repository-native sources were `agent-test/local/rules.md`, `agent-test/local/edge-smoke.md`, the active plan/review pair, SDD S05, existing coordinator tests, and fresh reviewer commands.
- Local preflight: `/config/.local/bin/go` resolves to `/config/opt/go/bin/go`; `go version go1.26.2 linux/arm64`; `GOROOT=/config/opt/go`; module directive is Go 1.24.
- Required execution stays in the current checkout and uses deterministic package tests, the race detector, vet, formatting, and diff checks. No external runner, credential, live provider, or smoke environment is needed because endpoint handler integration remains excluded.
- The current worktree contains intentional sibling execution-preset changes; verification must preserve them and judge only this task's files plus direct package regressions.
- Confidence: high. Both blocking defects have direct fresh reproducers, and the required successor behavior has deterministic local assertions.

### Test Coverage Gaps

- Existing canonicalization coverage checks only Chat object key order; it does not prove lossless large JSON numbers, structured Chat content, Anthropic history/tool schemas, or mutation rejection.
- Existing frontier coverage checks duplicate result consumption but not duplicate provider IDs in one expected set or replay of an already consumed mapping in a later frontier.
- TTL expiry is covered, but request capacity, per-frontier bounds, per-request mapping bounds, and no-mutation-on-rejection are not.
- Admission tests do not reject an empty preset generation.

### Symbol References

- No production caller uses `newChatRequestLineage`, `newAnthropicRequestLineage`, or the coordinator outside `request_coordinator_test.go`; `Server.logicalRequests()` is the only current ownership accessor. Signature changes remain confined to this package and its tests.
- No symbol is removed from an external package API.

### Split Judgment

Keep one plan. Lossless lineage, bijective never-reused tool IDs, and bounded admission form one continuation-fence invariant; splitting them would allow an independently passing coordinator that still admits ambiguous or unbounded state.

### Scope Rationale

Change only the coordinator, lineage helper, and their tests. Do not integrate Chat/Anthropic handlers, add mode transitions or workspace artifact semantics, change external contracts, alter `Server` ownership, or touch sibling execution-preset work.

### Final Routing

- `evaluation_mode=isolated-reassessment`; `finalizer=finalize-task-policy.sh`, pair mode.
- Build closures are all true. Scores `(2,2,1,2,1)` produce G08 with local-fit base. `large_indivisible_context=false`; matched risks are `temporal_state`, `concurrent_consistency`, `boundary_contract`, `structured_interpretation`, and `variant_product` (5). `review_rework_count=2` and `evidence_integrity_failure=true` trigger `recovery-boundary`; build route is cloud `PLAN-cloud-G08.md`.
- Review closures are all true. Scores `(2,2,1,2,1)` produce official cloud G08 in `CODE_REVIEW-cloud-G08.md` using Codex `gpt-5.6-sol` xhigh.
- No capability gap or external decision remains.

## Implementation Checklist

- [ ] Preserve lossless endpoint canonical JSON for immutable Chat/Anthropic lineage and add meaningful history/tool-schema mutation coverage.
- [ ] Enforce non-empty preset generation, bijective never-reused tool IDs, and explicit per-frontier/per-request bounds without partial mutation.
- [ ] Run archived dependency, focused, race, vet, formatting, and diff verification exactly as written.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_API-1] Preserve Lossless Endpoint Lineage

#### Problem

`request_lineage.go:29-40` hashes `chatCompletionRequest` after `Tools []any` and `chatMessage` have already passed through lossy decoding. Distinct JSON Schema integer constraints above IEEE-754 exact range can therefore hash identically, and structured content can be discarded before the immutable history digest is built. Anthropic lineage lacks mutation/canonical-equivalence coverage.

#### Solution

Build endpoint lineage from bounded raw/canonical JSON owned by the ingress boundary. Decode canonical components with `json.Decoder.UseNumber`, preserve supported structured message/tool values, separate the committed immutable prefix from the new continuation frontier, and hash only canonical semantic values plus the endpoint tag.

```go
// Before: request_lineage.go:29
func newChatRequestLineage(req chatCompletionRequest) (logicalRequestLineage, error) {
    tools, err := fingerprintCanonicalJSON(logicalRequestEndpointChat, req.Tools)
    // ...
}

// After: preserve raw JSON number and structured-value fidelity before typed decoding.
func newChatRequestLineage(raw json.RawMessage) (logicalRequestLineage, error) {
    envelope, err := decodeLogicalRequestLineageEnvelope(raw, logicalRequestEndpointChat)
    if err != nil {
        return logicalRequestLineage{}, err
    }
    return fingerprintLogicalRequestLineage(envelope)
}
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/request_lineage.go` — decode and fingerprint lossless endpoint canonical values and immutable prefixes.
- [ ] `apps/edge/internal/openai/request_coordinator_test.go` — add Chat/Anthropic equivalence and mutation regression matrices, including large JSON Schema integers.

#### Test Strategy

Add `TestLogicalRequestLineageMutationMatrix` with Chat and Anthropic fixtures. Assert whitespace/key-order equivalence hashes equally, while committed history, structured content, tool schema, endpoint, and adjacent large integer constraints hash differently.

#### Verification

Run `go test -count=1 ./apps/edge/internal/openai -run 'TestLogicalRequestLineage'`; expect PASS.

### [REVIEW_API-2] Enforce Bijective Replay-Safe Bounded State

#### Problem

`request_coordinator.go:227-245` stages public IDs but does not track provider IDs within the same frontier before mutating persistent maps. It also permits a consumed public/provider pair to become expected again. `request_coordinator.go:214-250` accepts unbounded frontier and cumulative mapping sizes, while `request_coordinator.go:384-391` allows an empty preset generation.

#### Solution

Add explicit default/configurable frontier and per-request mapping limits. Validate non-empty preset generation at admission. During `awaitToolResults`, build local public/provider sets, reject any same-frontier collision or previously recorded public/provider ID, enforce both bounds, and perform no record mutation until all validation passes. Retain mappings only for correlation while treating every recorded ID as consumed/non-reusable after its frontier succeeds.

```go
// Before: request_coordinator.go:227
frontier := make(map[string]string, len(expected))
for _, item := range expected {
    if _, duplicate := frontier[item.PublicCallID]; duplicate {
        return logicalRequestSnapshot{}, errLogicalRequestFrontier
    }
}

// After: validate a bounded bijection and replay fence before mutation.
frontier := make(map[string]string, len(expected))
providers := make(map[string]struct{}, len(expected))
for _, item := range expected {
    if recordedOrDuplicate(record, frontier, providers, item) {
        return logicalRequestSnapshot{}, errLogicalRequestFrontier
    }
}
```

#### Modified Files and Checklist

- [ ] `apps/edge/internal/openai/request_coordinator.go` — generation admission, frontier/mapping bounds, batch bijection, and cross-frontier replay rejection.
- [ ] `apps/edge/internal/openai/request_coordinator_test.go` — collision, replay, limit boundary, no-mutation, capacity, and admission tests.

#### Test Strategy

Add `TestLogicalRequestToolMappingCollisionAndReplay`, `TestLogicalRequestBoundsDoNotMutate`, and `TestLogicalRequestAdmissionRequiresPresetGeneration`. Cover duplicate public and provider IDs, previously consumed public/provider IDs, exact/over limit, request capacity after TTL eviction, and unchanged snapshots after rejection. Keep the existing 32-caller race test.

#### Verification

Run `go test -race -count=1 ./apps/edge/internal/openai -run 'TestLogicalRequest'`; expect PASS with exactly one concurrent frontier consumer.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/edge/internal/openai/request_lineage.go` | REVIEW_API-1 |
| `apps/edge/internal/openai/request_coordinator.go` | REVIEW_API-2 |
| `apps/edge/internal/openai/request_coordinator_test.go` | REVIEW_API-1, REVIEW_API-2 |
| `agent-task/m-iop-hot-path-one-shot-execution/05+02,04_request_coordinator/CODE_REVIEW-cloud-G08.md` | REVIEW_API-1, REVIEW_API-2 |

## 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
go test -count=1 ./apps/edge/internal/openai -run 'TestLogicalRequestLineage'
go test -race -count=1 ./apps/edge/internal/openai -run 'TestLogicalRequest'
go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai ./apps/edge/internal/service
go vet ./apps/edge/internal/openai
gofmt -d apps/edge/internal/openai/request_coordinator.go apps/edge/internal/openai/request_lineage.go apps/edge/internal/openai/request_coordinator_test.go
git diff --check
```

Expected: every command exits 0; distinct supported Chat/Anthropic mutations have distinct fingerprints, formatting/key-order equivalents remain stable, duplicate/replayed IDs and over-limit inputs fail without mutation, and exactly one concurrent continuation consumes the frontier.

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