<!-- task=m-iop-owned-single-request-agent-execution/14+05,12,13_observation_timing plan=1 tag=API milestone-task=cleanup-observation -->

# Closed Single-request Observation Timing Semantics

## For the Implementing Agent

Do not start until packets 05, 12, and 13 each have `complete.log`. Define and instrument only the service-owned closed observation and timing semantics, run every listed command, and fill `CODE_REVIEW-cloud-G07.md`. Review finalization remains outside this packet.

## Background

The completed ingress, internal-tool, and cleanup lifecycle needs a closed, copy-safe event model and deterministic timing ownership before production metrics/log adapters can consume it. This packet defines that service boundary and proves timing and terminal behavior without adding adapters or HTTP evidence.

## Analysis

### Files Read

- `apps/edge/internal/service/service.go`
- `apps/edge/internal/openai/hot_path_observation.go`
- `packages/go/observability/observability.go`
- `agent-spec/runtime/edge-node-execution.md`

### SDD Criteria

- S07 requires raw-free request/stage/tool/cleanup/total timing and outcomes across success/error/cancel.
- Stage pure time excludes internal-tool execution, while total time includes cleanup and terminal resolution.
- Observation failure must never change lifecycle semantics.

### Verification Context

- Existing Hot Path observation provides the repository pattern for closed enums, allowlists, injected sinks, and failure isolation.
- Packets 12 and 13 supply the stable lifecycle seams consumed here.
- Deterministic service tests use an injected clock and observer; no external runner is required.

### State and Concurrency Findings

- The terminal winner owns exactly one terminal event and one request-total event.
- Provider-active timing pauses during `internal_tool` execution and resumes on continuation.
- Observer panic/error must be contained outside request state transitions.

### Test Coverage Gaps

- No closed single-request observation DTO, stage-pure accumulator, or lifecycle observer exists.
- No deterministic test covers success/error/cancel races, timing math, sanitization, or observer failure.

### Symbol References

- Add a distinct service-owned observer; do not merge it with route-01 `hotPathObserver`.
- Instrument packet 12's tool-loop seam and packet 13's cleanup/terminal lifecycle without changing their outcomes.
- No API, wire, config, metrics adapter, bootstrap, or Node log changes belong here.

### Split Judgment

- The closed schema and timing state form one service-local correctness unit with a deterministic race test.
- Edge/Node adapters consume this boundary in packet 15; HTTP/spec closure follows in packet 16.

### Scope Rationale

- Include closed DTO/enums, explicit allowlists/sanitization, injected clock/observer, timing accumulation, lifecycle hooks, and deterministic service tests.
- Exclude Prometheus/zap production adapters, bootstrap wiring, Node logs, HTTP correlation, spec updates, and external smoke.

### Final Routing

- `evaluation_mode=isolated-reassessment`; build closures are true; scores 1/2/1/1/1 = G06.
- Finalizer `finalize-task-policy.sh` in `pair` mode selected `local-fit`, lane `local`, filename `PLAN-local-G06.md`.
- Build signals: `large_indivisible_context=false`; positive risks `temporal_state`, `concurrent_consistency`, `variant_product` (3); no rework or evidence-integrity failure.
- Review closures are true; scores 1/2/1/2/1 = G07; official review filename `CODE_REVIEW-cloud-G07.md`.

## Dependencies and Execution Order

1. Require packets 05, 12, and 13 to complete.
2. Define the closed observation contract and injected clock/observer.
3. Instrument request, stage, tool, cleanup, terminal, and total seams, then prove the timing/race invariants.

## Implementation Checklist

- [ ] Define a closed, copy-safe single-request observation schema and explicit allowlists that exclude all raw or unbounded values.
- [ ] Measure request total, provider-active stage, Node tool, and cleanup durations/outcomes exactly once without counting tool time as stage pure time.
- [ ] Prove timing math, terminal races, observer panic/error isolation, and secret-sentinel sanitization with a deterministic service test.
- [ ] Run dependency, focused race, package, vet, and whitespace verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Implementation Plan

### [API-1] Define closed observation and timing semantics

**Problem**

- `apps/edge/internal/service/service.go:28` has no observer or clock for the packet 03/12/13 lifecycle.
- `apps/edge/internal/openai/hot_path_observation.go:1` is route-01-specific and has different states and identities.

**Solution**

Add service-owned closed enums for event class (`request`, `stage`, `tool`, `cleanup`, `terminal`), stage (`plan`, `work`, `review`), operation, and outcome/error class. The DTO may include a bounded generated execution correlation id for later logs, but it contains only closed identities, durations/counts, and truncated booleans. It never contains request text, public model, provider id, Node/root/path, command/template/env, tool input/output, error string, header, credential, or raw terminal.

Add an injectable clock and failure-isolated observer snapshot on `Service`. Accumulate provider-active stage intervals around `internal_tool`, record Node tool duration once, cleanup once, terminal once, and request total after acknowledgement/cancel resolution. Unknown enum/value normalizes to empty and is dropped.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/service/service.go` — configure and snapshot the observer and clock safely.
- [ ] `apps/edge/internal/service/single_request_observation.go` — add closed DTO/enums, allowlists, sanitizer, timer accumulation, and safe emit.
- [ ] `apps/edge/internal/service/single_request.go` — add request/stage/terminal/total timing hooks.
- [ ] `apps/edge/internal/service/single_request_tool_loop.go` — add tool pause/resume timing hooks.
- [ ] `apps/edge/internal/service/single_request_observation_test.go` — cover deterministic timing, success/error/cancel/race, schema/sentinel, and observer failure.

**Test Strategy**

- Use a manual clock and capturing/panicking observer. Assert exact event count/order and `stage_active + tool + cleanup <= total`, with tool duration excluded from stage active time.

**Verification**

- `go test -race ./apps/edge/internal/service -run 'TestSingleRequestObservation' -count=1`
- Expected: timing/event ownership is deterministic and observer failure never changes terminal behavior.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/service/service.go` | API-1 |
| `apps/edge/internal/service/single_request_observation.go` | API-1 |
| `apps/edge/internal/service/single_request.go` | API-1 |
| `apps/edge/internal/service/single_request_tool_loop.go` | API-1 |
| `apps/edge/internal/service/single_request_observation_test.go` | API-1 |
| `agent-task/m-iop-owned-single-request-agent-execution/14+05,12,13_observation_timing/CODE_REVIEW-cloud-G07.md` | API-1 |

## Final Verification

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/05+03_single_ingress/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/05+03_single_ingress/complete.log' | wc -l)" -eq 1`
2. `test -f agent-task/m-iop-owned-single-request-agent-execution/12+05,06,08,11_internal_tool_loop/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/12+05,06,08,11_internal_tool_loop/complete.log' | wc -l)" -eq 1`
3. `test -f agent-task/m-iop-owned-single-request-agent-execution/13+12_workspace_cleanup/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/13+12_workspace_cleanup/complete.log' | wc -l)" -eq 1`
4. `go test -race ./apps/edge/internal/service -run 'TestSingleRequestObservation' -count=1`
5. `go test ./apps/edge/internal/service -count=1`
6. `go vet ./apps/edge/internal/service`
7. `git diff --check`

Expected: all predecessors are uniquely complete; closed timing math, terminal ownership, sanitization, and observer failure isolation pass; the service package remains clean. Cached tests are not acceptable.

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