<!-- task=m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission plan=2 tag=REVIEW_REVIEW_API milestone-task=workspace-binding -->

# Close Workspace Admission Test and Evidence Gaps

## For the Implementing Agent

Implement Required R1, R3, and R5 exactly within `Modified Files Summary`, run every verification command, and fill all implementation-owned sections in `CODE_REVIEW-cloud-G08.md` with actual notes and stdout/stderr. Keep the active pair in place and report ready for review. If blocked, record only the exact blocker, attempted command/output, and resume condition in implementation-owned evidence; do not ask the user, call user-input tools, create stop files, classify the next state, archive logs, or write `complete.log`.

## Background

The second workspace-admission review confirmed the production fail-closed binding and operation-aware limits, but removing the zero-value service bypass broke OpenAI coordinator tests that still call the public service without a workspace catalog or ready registry owner. The new race tests also remain schedule-dependent or serial and do not complete the required rejection matrix. This follow-up repairs those test boundaries before rerunning the previously contradicted full Edge evidence.

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission/plan_cloud_G08_1.log`
- Prior review: `agent-task/m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission/code_review_cloud_G09_1.log`
- Verdict: `FAIL`; routing signals: `review_rework_count=2`, `evidence_integrity_failure=true`.
- Required findings: R1 replace stale zero-value OpenAI public-service test fixtures with exact admitted workspace fixtures; R3 add deterministic reconnect/refresh handshakes and malformed/unsupported public rejection rows; R5 rerun and record complete full Edge evidence after those fixes.
- Fresh reviewer evidence: dependency, formatting, named registry/service race, focused node/service, vet, spec search, and whitespace checks passed. `go test ./apps/edge/internal/openai -count=1 -timeout=15s` reported eight single-request failures and timed out in `TestAnthropicSingleRequestCallerCancellationCancelsExecution`; the exact full Edge command did not complete in that package.
- Closed findings: R2 operation-specific zero limits and R4 living-spec synchronization are accepted and must not be reopened without a concrete regression.
- Roadmap carryover: `milestone-task=workspace-binding`; SDD S04 fail-closed workspace admission evidence remains the contribution target, while Node-private filesystem/symlink enforcement remains later work.

## Finding Resolution Map

| Finding | Mode | Exact resolution | Changed precondition |
|---------|------|------------------|----------------------|
| R1 | `direct-fix` | Add one real admitted-service helper in `single_request_handler_test.go`, use it from every buffered/streaming public-service fixture, and assert the executor receives the expected frozen workspace projection. | Public `StartSingleRequest` tests now satisfy the same exact catalog/ready-owner admission required in production instead of depending on the removed bypass. |
| R3 | `direct-fix` | Replace the registry start-only race with per-transition handshakes; coordinate service refresh/reconnect from separate goroutines inside the bind-to-handoff window; add malformed and unsupported public rejection rows with executor-call assertions. | Named race tests deterministically exercise the intended transitions and the rejection matrix proves zero executor calls for every owned variant. |
| R5 | `direct-fix` | Fill the new review artifact only after the changed test preconditions pass, then run the exact full Edge command through `internal/openai`, `internal/service`, and remaining packages to a real exit status. | Full-suite verification is repeated only after R1/R3 change the failing precondition and complete stdout/stderr can be trusted. |

## Analysis

### Files Read

- `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-test/local/rules.md`
- `agent-test/local/edge-smoke.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-contract/index.md`
- `agent-contract/inner/edge-config-runtime-refresh.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `agent-spec/index.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-task/m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission/plan_cloud_G08_1.log`
- `agent-task/m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission/code_review_cloud_G09_1.log`
- `apps/edge/internal/node/registry.go`
- `apps/edge/internal/node/registry_test.go`
- `apps/edge/internal/node/store.go`
- `apps/edge/internal/service/service.go`
- `apps/edge/internal/service/single_request_types.go`
- `apps/edge/internal/service/single_request_workspace.go`
- `apps/edge/internal/service/single_request_workspace_test.go`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/server.go`
- `apps/edge/internal/openai/single_request_preset_binding.go`
- `apps/edge/internal/openai/single_request_handler_test.go`
- `apps/edge/internal/openai/single_request_anthropic_stream_test.go`

### SDD Criteria

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`; status `[승인됨]`, lock released.
- Milestone scope: `milestone-task=workspace-binding`.
- Acceptance Scenario S04 requires approved workspace execution and pre-execution rejection of unapproved ref, foreign Node/path, and escape candidates.
- Evidence Map S04 requires a workspace route/path/symlink admission table and fail-closed evidence. This follow-up closes the Edge catalog-owner/generation slice with deterministic zero-executor evidence; Node-private path/symlink enforcement remains the later executor packet.
- The checklist and final verification therefore require real public-service admission fixtures, the complete Edge-owned rejection matrix, generation/refresh synchronization, and fresh full Edge evidence.

### Verification Context

- No separate verification handoff was supplied. Repository-native fallback came from the archived review, active source/tests, local Edge smoke profile, and fresh reviewer commands.
- Current host: `/config/workspace/iop-s0`, Linux arm64, Go `1.26.2`; no credential or external service is required.
- Preconditions: packet 03 and packet 07 dependency checks each exit 0.
- Fresh passing evidence: formatting; named node/service race commands; focused node/service packages; `go vet ./apps/edge/...`; deterministic spec search; `git diff --check`.
- Fresh failing evidence: the exact full Edge run enters `internal/openai` but does not complete. The bounded diagnostic reports eight workspace-admission-derived failures and a timeout blocked on a controller callback that never occurs.
- External Verification Preflight: not applicable. This is a deterministic test-boundary repair and does not implement the Node executor/wire or actual Mac/Claude execution.
- Confidence is high because the failing zero-value fixtures directly call the newly fail-closed public service and the bounded package diagnostic identifies every affected endpoint test.

### Test Coverage Gaps

- Public OpenAI service fixtures do not configure the opaque workspace ref, catalog owner, and ready registry generation required by production admission.
- The registry test releases both goroutines from one start channel but does not prove that snapshot reads occur across reconnect transitions.
- Service refresh and reconnect mutations run synchronously in the test hook rather than through coordinated concurrent actors.
- Malformed and unsupported workspace catalogs are tested only through an internal compiler path, not through public service rejection with executor non-invocation.
- Full Edge verification is contradicted and incomplete until the above preconditions change.

### Symbol References

- No symbol is renamed or removed.
- Stale public-service fixtures: `single_request_anthropic_stream_test.go:410,651` and `single_request_handler_test.go:155,279,324,349`.
- Production public callers remain `anthropic_handler.go:223,258`; they must continue to use exact service admission.

### Split Judgment

- Keep one atomic follow-up. The shared OpenAI admitted-service fixture, Edge admission matrix, deterministic generation/refresh scheduling, and full Edge oracle must agree before this S04 contribution is judgeable.
- The existing split dependencies `03` and `07` remain satisfied by their unique archived `complete.log` files; there is no dependency wait.

### Scope Rationale

- Include only the two OpenAI single-request test files, registry snapshot test, service workspace-admission test, and implementation-owned review evidence.
- Exclude production admission code, config schema, contracts, living spec, protobuf, Node executor/wire, filesystem containment, provider stages, and roadmap mutation. R2/R4 production and documentation changes already pass direct review.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer `finalize-task-policy.sh pair`.
- Build closures: scope/context/verification/evidence/ownership/decision all closed; scores `2/2/0/2/2` = `G08`; base `local-fit`, final basis `recovery-boundary`, lane `cloud`, filename `PLAN-cloud-G08.md`.
- Review closures: all closed; scores `2/2/0/2/2` = `G08`; basis `official-review`, lane `cloud`, filename `CODE_REVIEW-cloud-G08.md`.
- `large_indivisible_context=false`; positive loop risks: `temporal_state`, `concurrent_consistency`, `boundary_contract`, `variant_product` (4).
- Recovery signals: `review_rework_count=2`, `evidence_integrity_failure=true`; no capability gap.

## Dependencies and Execution Order

1. Preserve the accepted production admission and R2/R4 changes.
2. Repair R1 fixtures before running endpoint tests that wait for executor callbacks.
3. Complete R3 deterministic race/matrix coverage, then run fresh verification and fill R5 evidence.

## Implementation Checklist

- [ ] Restore every OpenAI coordinator test that uses the public service with an exact configured workspace catalog and ready owner, preserving buffered/streaming endpoint assertions and proving the frozen workspace reaches the executor.
- [ ] Replace schedule-dependent registry/service race cases with deterministic transition handshakes and extend the public admission matrix through malformed and unsupported workspaces with zero executor calls.
- [ ] Run exact dependency, formatting, stale-fixture search, named race, OpenAI, focused, full Edge, vet, documentation, and whitespace verification to completion.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [FIX-1] Restore admitted OpenAI public-service fixtures

**Problem**

- `apps/edge/internal/openai/single_request_anthropic_stream_test.go:410` and `:651` create `&edgeservice.Service{}` and call the public service after its zero-runtime bypass was removed.
- `apps/edge/internal/openai/single_request_handler_test.go:155,279,324,349` repeats the same stale fixture, producing 502 responses or blocking forever on executor/controller channels.

**Solution**

Before (`apps/edge/internal/openai/single_request_handler_test.go:155`):

```go
svc := &edgeservice.Service{}
svc.SetSingleRequestExecutor(executor)
```

After:

```go
svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref")
```

Add a shared test helper using `edgenode.NewRegistry`, one registered ready `NodeEntry`, `edgenode.NewNodeStore`, and read-only `config.WorkspaceDefinition` entries for the exact requested refs. Import `edgenode "iop/apps/edge/internal/node"` in the helper owner. Use `"opaque-workspace"` for direct stream-pump bindings and `"ws-opaque-ref"` for preset-backed HTTP tests. Do not restore a production bypass or substitute a fake `singleRequestService`; these tests must exercise public workspace admission. Extend the captured request assertion to require the expected ref, Node id, nonzero generation, and closed read capability.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/openai/single_request_handler_test.go` — add the admitted-service helper, replace all buffered public-service fixtures, and assert the frozen workspace projection.
- [ ] `apps/edge/internal/openai/single_request_anthropic_stream_test.go` — use the helper for direct pump and streaming public-service fixtures.

**Test Strategy**

- Keep every existing endpoint/lifecycle assertion and make the real admitted fixture the regression oracle. `TestAnthropicSingleRequestUsesOnePost` additionally verifies the executor receives the bound workspace; the caller-cancellation case must no longer block before executor startup.

**Verification**

- `rg --sort path -n 'svc := &edgeservice.Service\\{\\}' apps/edge/internal/openai/single_request_handler_test.go apps/edge/internal/openai/single_request_anthropic_stream_test.go`
- `go test ./apps/edge/internal/openai -run '^(TestSingleRequestAnthropic|TestAnthropicSingleRequest)' -count=1 -timeout=30s`
- Expected: the search has no output, every selected test completes without timeout, and the package exits 0.

### [FIX-2] Make admission race and rejection evidence deterministic

**Problem**

- `apps/edge/internal/node/registry_test.go:368` only uses a common start channel; scheduler order can let either loop finish without observing a reconnect transition.
- `apps/edge/internal/service/single_request_workspace_test.go:142` lacks malformed/unsupported public-service rows, while `:196` and `:218` execute refresh/reconnect serially inside the caller goroutine.

**Solution**

Before (`apps/edge/internal/node/registry_test.go:368`):

```go
start := make(chan struct{})
// Both loops start after close(start), without a per-transition rendezvous.
```

After:

```go
snapshotStep := make(chan int)
transitionDone := make(chan int)
// Each reconnect transition and snapshot assertion rendezvous explicitly.
```

Use bounded per-step channels so the reader and reconnect actor confirm unavailable/ready generations around every ownership transition; no sleeps or start-only scheduling assumptions are allowed. In service tests, launch refresh/reconnect actors before `StartSingleRequest`, release them from `beforeSingleRequestHandoff`, wait for their completion through channels, and assert frozen binding or stale rejection. Add malformed empty/duplicate/unknown-operation and command-without-command-operation cases to the public admission table with a real ready owner and `executor.calls == 0`.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/node/registry_test.go` — replace the start-only loop with deterministic transition rendezvous and monotonic/self-consistent generation assertions.
- [ ] `apps/edge/internal/service/single_request_workspace_test.go` — coordinate refresh/reconnect actors and complete public malformed/unsupported rejection coverage.

**Test Strategy**

- Keep both selected test names under the exact `-run` commands. Assert every transition is observed, stale generations never reach the executor, refresh retains one copied binding, and every rejection calls the executor zero times.

**Verification**

- `go test -race ./apps/edge/internal/node -run 'TestRegistryReadyOwnerSnapshot' -count=1`
- `go test -race ./apps/edge/internal/service -run 'TestSingleRequestWorkspace' -count=1`
- Expected: named tests execute with deterministic handshakes, no `[no tests to run]`, no race report, and exit 0.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/openai/single_request_handler_test.go` | FIX-1 |
| `apps/edge/internal/openai/single_request_anthropic_stream_test.go` | FIX-1 |
| `apps/edge/internal/node/registry_test.go` | FIX-2 |
| `apps/edge/internal/service/single_request_workspace_test.go` | FIX-2 |
| `agent-task/m-iop-owned-single-request-agent-execution/08+03,07_workspace_admission/CODE_REVIEW-cloud-G08.md` | FIX-1, FIX-2, R5 evidence |

## Final Verification

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/03+02_single_request_coordinator/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/03+02_single_request_coordinator/complete.log' | wc -l)" -eq 1`
2. `test -f agent-task/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/complete.log' | wc -l)" -eq 1`
3. `test -z "$(gofmt -l apps/edge/internal/openai/single_request_handler_test.go apps/edge/internal/openai/single_request_anthropic_stream_test.go apps/edge/internal/node/registry_test.go apps/edge/internal/service/single_request_workspace_test.go)"`
4. `test -z "$(rg --sort path -l 'svc := &edgeservice.Service\\{\\}' apps/edge/internal/openai/single_request_handler_test.go apps/edge/internal/openai/single_request_anthropic_stream_test.go)"`
5. `go test -race ./apps/edge/internal/node -run 'TestRegistryReadyOwnerSnapshot' -count=1`
6. `go test -race ./apps/edge/internal/service -run 'TestSingleRequestWorkspace' -count=1`
7. `go test ./apps/edge/internal/openai -run '^(TestSingleRequestAnthropic|TestAnthropicSingleRequest)' -count=1 -timeout=30s`
8. `go test -race -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service`
9. `go test ./apps/edge/internal/node ./apps/edge/internal/service -count=1`
10. `go test ./apps/edge/... -count=1`
11. `go vet ./apps/edge/...`
12. `rg --sort path -n 'workspace_ref|connection generation|admission|reselect|defer' agent-spec/runtime/edge-node-execution.md`
13. `git diff --check`

Expected: both predecessors resolve uniquely; formatting and stale-fixture searches are clean; all named, OpenAI, race, focused, and full Edge tests finish uncached with exit 0; vet and whitespace pass; the accepted living spec remains synchronized. Cached Go output is not acceptable.

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