<!-- task=m-iop-owned-single-request-agent-execution/15+14_observation_adapters plan=1 tag=REVIEW_API milestone-task=cleanup-observation -->

# Close Cleanup Integration and Preserve Observation Correlation

## For the Implementing Agent

Resolve only Required findings R1 and R2 from the archived review. Keep the existing lifecycle, wire, API, config, and observation schemas unchanged; do not substitute a verification-only workaround for either fix. Run every listed command and fill `CODE_REVIEW-cloud-G06.md` before reporting ready for review.

## Background

The first implementation loop added the bounded Edge and Node observation adapters, and its focused observation tests passed. Review found one stale HTTP integration harness that cannot answer the now-mandatory cleanup request and one cleanup/tool ordering race that can detach a successful tool event from its request correlation.

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/plan_cloud_G07_0.log`.
- Prior review: `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/code_review_cloud_G08_0.log`.
- Prior verdict: `FAIL`; Required findings: R1 and R2; Suggested findings: none; Nit findings: none.
- R1 evidence: the focused observation race suite passed, but `TestAnthropicSingleRequestInternalToolsStayPrivate` failed three consecutive targeted runs because the fake proto-socket had no cleanup request/response registration; a short-timeout goroutine dump showed `Service.workspaceCleanup` waiting in `WorkspaceCleanupRequest`.
- R2 evidence: a deterministic temporary cleanup/WRITE ordering test emitted a non-empty `ws-*` cleanup correlation followed by an empty successful WRITE correlation; the temporary review test was removed after reproduction.
- Supporting verification: `go vet` and `git diff --check` passed; the approved SDD `cleanup-observation` criterion remains the governing closure target.

## Analysis

### Files Read

- `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/plan_cloud_G07_0.log`
- `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/code_review_cloud_G08_0.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-spec/runtime/edge-node-execution.md`
- `agent-spec/input/openai-compatible-surface.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `agent-contract/outer/anthropic-compatible-api.md`
- `apps/edge/internal/openai/single_request_handler_test.go`
- `apps/edge/internal/service/workspace_wire.go`
- `apps/node/internal/workspace/observation.go`
- `apps/node/internal/workspace/runtime.go`
- `apps/node/internal/workspace/cleanup.go`
- `apps/node/internal/workspace/file_executor.go`
- `apps/node/internal/workspace/command_executor.go`
- `apps/node/internal/workspace/observation_test.go`
- `apps/node/internal/workspace/runtime_test.go`
- `apps/node/internal/workspace/file_executor_test.go`

### SDD Criteria

- The approved SDD is unlocked and assigns this task to `milestone-task=cleanup-observation`.
- S07 requires linked, raw-free tool and cleanup evidence. A terminal HTTP path must complete cleanup, and every tool event must retain the same non-empty request-local correlation even when cleanup overlaps the operation.
- The Evidence Map requires bounded timing/log/metric evidence without path, command, output, credential, request id, or other raw values. Neither finding permits expanding that allowlist.

### Verification Context

- The host reports Go `1.26.2` on `linux/arm64`; changes must remain compatible with the repository's Go target.
- Packet 14 has exactly one archived `complete.log` and remains the closed dependency for observation timing.
- The original focused race tests pass. The OpenAI package regression fails deterministically at cleanup, while the Node correlation defect was reproduced with an ordering-controlled race test.
- No external executor, handoff, or user choice is required; both fixes and their evidence are repository-local.

### State and Concurrency Findings

- The fake server registers open and tool protocol pairs only. Once terminal cleanup became mandatory, the HTTP request waits for a response that the fake cannot parse or emit.
- `observeTool` currently obtains correlation by looking up `requestID` after a tool operation returns. Concurrent cleanup may delete the request before that lookup, so post-operation observation can lose correlation despite successful execution.
- Correlation must be captured while the tool still owns valid request state and carried as immutable data into the deferred observer. Cleanup authority and request-map deletion semantics must remain unchanged.

### Test Coverage Gaps

- The Anthropic internal-tool integration test does not model or count the terminal workspace cleanup exchange.
- Node observation tests cover normal serial emission but do not force cleanup between correlation acquisition and deferred tool observation.

### Symbol References

- R1 centers on `newAnthropicInternalToolService` and `TestAnthropicSingleRequestInternalToolsStayPrivate` in `apps/edge/internal/openai/single_request_handler_test.go`; production `Service.workspaceCleanup` and `WorkspaceCleanupRequest` are evidence, not modification targets.
- R2 centers on `observeTool` in `apps/node/internal/workspace/observation.go` and its deferred call sites in READ, LIST, WRITE, DELETE, and COMMAND execution paths.
- The request-local `ws-*` value is generated at Open and must be reused; do not derive it from raw request identifiers or create a replacement at observation time.

### Review Finding Resolution Map

| Finding | Disposition | Owner and exact resolution |
|---------|-------------|----------------------------|
| R1 | Direct fix | In `apps/edge/internal/openai/single_request_handler_test.go`, register the cleanup request/response protocol pair in the fake proto-socket, return the canonical successful cleanup response, and assert exactly one terminal cleanup in the Anthropic internal-tool flow. |
| R2 | Direct fix | In `apps/node/internal/workspace/observation.go`, `file_executor.go`, and `command_executor.go`, capture immutable correlation while request ownership is valid and pass it to deferred tool observation for READ/LIST/WRITE/DELETE/COMMAND; add an ordering-controlled regression in `observation_test.go` proving cleanup and tool events share one non-empty correlation. |

`ownership_closed=true`: both Required findings have one direct repository-local owner, and no Suggested or Nit findings remain.

### Split Judgment

- Keep one follow-up packet. R1 restores the required integrated package oracle and R2 repairs the same task's S07 linked-observation invariant; both must close before this observation-adapter task can pass review.
- The write set is compact and the fixes share one final verification surface. Splitting would create an intermediate state that still cannot satisfy the task verdict.

### Scope Rationale

- Include the OpenAI test fake's cleanup exchange/count assertion, immutable Node correlation propagation at five existing tool seams, and deterministic regression coverage.
- Exclude production cleanup semantics, service coordinator behavior, request/result schemas, API/wire/config contracts, metrics/log field expansion, spec edits, and the separate packet 16 full-cycle/external-smoke closure.

### Final Routing

- `evaluation_mode=isolated-reassessment`; build and review closure checks are all true.
- The finalizer was invoked exactly once as `finalize-task-policy.sh pair local-fit false 3 1 false 1 2 0 2 1 official-review 1 2 0 2 1`.
- Positive loop risks are `temporal_state`, `concurrent_consistency`, and `boundary_contract` (`loop_risk_count=3`); `large_indivisible_context=false`, `review_rework_count=1`, and `evidence_integrity_failure=false`.
- Build scores `1/2/0/2/1` select G06, lane `local`, route basis `local-fit`, and `PLAN-local-G06.md`.
- Review scores `1/2/0/2/1` select G06, lane `cloud`, route basis `official-review`, and `CODE_REVIEW-cloud-G06.md`.
- One archived plan log and one archived review log make this follow-up `plan=1`; the next eventual log suffix is `1` for each artifact kind.

## Dependencies and Execution Order

1. Confirm packet 14 remains uniquely complete.
2. Repair the Anthropic test fake and its exact-one cleanup assertion.
3. Capture and propagate immutable Node correlation at every tool observer call site, then add the ordering-controlled regression.
4. Run targeted, race, package, vet, and whitespace verification and fill the active review artifact.

## Implementation Checklist

- [ ] Register the canonical cleanup request/response in the Anthropic internal-tool fake and assert exactly one cleanup.
- [ ] Preserve one non-empty request-local correlation across cleanup overlap for READ, LIST, WRITE, DELETE, and COMMAND observations.
- [ ] Add deterministic regressions for the cleanup exchange and cleanup/tool ordering without weakening exact field/value allowlists.
- [ ] Run dependency, targeted, focused race, package, vet, and whitespace verification with uncached test runs.
- [ ] Fill every implementation-owned section in `CODE_REVIEW-cloud-G06.md` with actual decisions and command output.

## Implementation Plan

### [REVIEW_API-1] Complete the terminal cleanup integration harness

**Problem**

- `TestAnthropicSingleRequestInternalToolsStayPrivate` now enters mandatory terminal cleanup, but its fake proto-socket only handles workspace open and tool messages, so the HTTP path blocks until its context deadline.

**Solution**

Extend the existing fake parser/listener setup with the canonical workspace cleanup request and response pair. Return a successful cleanup response for the request under test, count cleanup calls, and require exactly one cleanup alongside the existing internal-tool privacy assertions. Do not change production coordinator or transport behavior.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/openai/single_request_handler_test.go` — add cleanup fake registration/response and exact-one terminal assertion.

**Test Strategy**

- Run the targeted test three times uncached so the prior deterministic five-second timeout cannot be hidden by cache or a single lucky run.
- Run the complete affected package regression after the fake is repaired.

**Verification**

- `go test ./apps/edge/internal/openai -run '^TestAnthropicSingleRequestInternalToolsStayPrivate$' -count=3`
- Expected: all three runs complete without timeout and each observed flow performs exactly one canonical cleanup.

### [REVIEW_API-2] Retain immutable tool correlation across cleanup overlap

**Problem**

- Deferred tool observation resolves correlation from the live request map after execution. Cleanup may delete that entry before observation, producing an empty correlation for a successful tool event.

**Solution**

Acquire the existing request-local correlation while the operation still owns valid request state, pass it explicitly to the deferred observer, and remove its dependence on a late request-map lookup. Apply the same invariant to READ, LIST, WRITE, DELETE, and COMMAND. Add an ordering-controlled test that pauses an operation, completes cleanup, resumes the operation, and asserts that the cleanup and tool records carry the same non-empty correlation while preserving the existing exact raw-free allowlist.

**Modified Files and Checklist**

- [ ] `apps/node/internal/workspace/observation.go` — accept immutable correlation at the tool observation seam instead of looking it up after completion.
- [ ] `apps/node/internal/workspace/file_executor.go` — capture and pass correlation for READ, LIST, WRITE, and DELETE.
- [ ] `apps/node/internal/workspace/command_executor.go` — capture and pass correlation for COMMAND.
- [ ] `apps/node/internal/workspace/observation_test.go` — add deterministic cleanup/tool ordering coverage and shared non-empty correlation assertions.

**Test Strategy**

- Force cleanup to remove request authority while a tool operation is paused, then release the operation under the race detector.
- Retain the existing exact key allowlist, forbidden-value sentinel, outcome, and observer-failure assertions.

**Verification**

- `go test -race ./apps/node/internal/workspace -run 'TestWorkspaceObservation' -count=1`
- Expected: all workspace observation tests pass under race detection, including shared non-empty correlation after cleanup overlap.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/openai/single_request_handler_test.go` | REVIEW_API-1 |
| `apps/node/internal/workspace/observation.go` | REVIEW_API-2 |
| `apps/node/internal/workspace/file_executor.go` | REVIEW_API-2 |
| `apps/node/internal/workspace/command_executor.go` | REVIEW_API-2 |
| `apps/node/internal/workspace/observation_test.go` | REVIEW_API-2 |
| `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/CODE_REVIEW-cloud-G06.md` | REVIEW_API-1, REVIEW_API-2 |

## Final Verification

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/14+05,12,13_observation_timing/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/14+05,12,13_observation_timing/complete.log' | wc -l)" -eq 1`
2. `go test ./apps/edge/internal/openai -run '^TestAnthropicSingleRequestInternalToolsStayPrivate$' -count=3`
3. `go test -race ./apps/node/internal/workspace -run 'TestWorkspaceObservation' -count=1`
4. `go test ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/edge/internal/openai ./apps/node/internal/workspace -count=1`
5. `go vet ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/edge/internal/openai ./apps/node/internal/workspace`
6. `git diff --check`

Expected: packet 14 remains uniquely complete; the Anthropic internal-tool flow performs one terminal cleanup without timeout; every tool/cleanup observation stays linked by the same non-empty raw-free correlation under forced overlap; all affected packages, vet, and whitespace checks pass. Cached tests are not acceptable.

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