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

# Bounded Edge and Node Observation Adapters

## For the Implementing Agent

Do not start until packet 14 has `complete.log`. Add only the bounded Edge metrics/zap adapter, bootstrap wiring, and raw-free Node workspace observer listed below, run every command, and fill `CODE_REVIEW-cloud-G08.md`. Do not change lifecycle outcomes or add HTTP/spec closure.

## Background

Packet 14 supplies the closed service observation contract and deterministic timing ownership. This packet projects that contract into bounded Edge metrics/logs and adds an equivalent raw-free Node workspace completion observer without exposing request-derived metric labels or runtime secrets.

## Analysis

### Files Read

- `apps/edge/internal/bootstrap/runtime.go`
- `apps/edge/internal/openai/server.go`
- `apps/edge/internal/openai/hot_path_metrics.go`
- `packages/go/observability/observability.go`
- `agent-spec/runtime/edge-node-execution.md`

### SDD Criteria

- S07 requires linked raw-free lifecycle observation and cleanup-preservation evidence.
- D10 forbids internal reasoning/tool protocol and raw command/path/output/credential values from observation.
- Metric labels must remain closed and bounded; observer failure must not affect runtime outcomes.

### Verification Context

- Packet 14 provides the service event DTO and safe observer seam consumed here.
- Packet 05 owns the no-label ingress counter; this packet only exposes the bounded correlation accessor needed later.
- Deterministic tests use a Prometheus gatherer and captured zap cores; no external runner is required.

### State and Concurrency Findings

- Collectors must register once and duplicate terminal attempts must not double-count.
- Production observers are installed before request handling and their failures are swallowed.
- Node tool/cleanup events must emit at common completion seams with exact key allowlists.

### Test Coverage Gaps

- No single-request lifecycle collectors or production zap adapter exists.
- Node workspace results have duration fields but no raw-free local observation seam.

### Symbol References

- Consume packet 14's service-owned observer; do not merge it with route-01 Hot Path observation.
- Extend packet 05's `single_request_metrics.go` only for its existing ingress test accessor.
- Do not change API/wire/config schemas or coordinator semantics.

### Split Judgment

- Edge/Node adapters and their wiring form one cross-component bounded-observation result.
- HTTP ingress-to-total correlation and living-spec synchronization remain the closure-only packet 16.

### Scope Rationale

- Include service Prometheus/zap adapter, collector tests, Edge bootstrap wiring, bounded ingress accessor, Node tool/cleanup observer, and raw-free tests.
- Exclude service timing semantics, HTTP integration evidence, specs, dashboards/ledger, external smoke, and semantic outcome changes.

### Final Routing

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

## Dependencies and Execution Order

1. Require packet 14's closed observation/timing boundary.
2. Add bounded Edge collectors/log projection and wire them before request handling.
3. Add the Node completion observer, then prove cardinality, allowlist, and failure-isolation behavior.

## Implementation Checklist

- [ ] Add failure-isolated bounded Prometheus/zap observers, wire them at Edge startup, and emit raw-free Node tool/cleanup logs.
- [ ] Prove collector cardinality, exact outcome counts, duplicate-terminal protection, exact log allowlists, secret-sentinel rejection, and observer panic/error isolation.
- [ ] Preserve packet 05 ingress ownership while exposing only the bounded test correlation needed by the later closure packet.
- [ ] 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-2] Emit bounded Edge metrics/logs and safe Node events

**Problem**

- Packet 05's planned `single_request_metrics.go` contains only `iop_anthropic_single_request_ingress_total`.
- Node workspace runtime has no allowlisted outcome log projection.

**Solution**

Create service lifecycle Prometheus histograms/counters with closed labels and a zap observer with an exact key allowlist. Register once, normalize Edge id, and expose test-only gather helpers without request-derived labels. In Edge bootstrap, install this observer on the service before input servers are created. Extend packet 05's test metric helper only as needed to compare ingress and request-total deltas later.

Add a workspace observer at the single `Runtime.Execute`/cleanup completion seams. Its exact zap fields are execution correlation, operation, closed outcome/error code, duration, truncation, process/artifact counts; never path/content/command/env/stdout/stderr. Observer failure is swallowed.

**Modified Files and Checklist**

- [ ] `apps/edge/internal/service/single_request_metrics.go` — add bounded collectors and production zap/metric observer.
- [ ] `apps/edge/internal/service/single_request_metrics_test.go` — cover collector labels/cardinality, exact deltas, and duplicate-terminal protection.
- [ ] `apps/edge/internal/bootstrap/runtime.go` — install the production observer before request handling.
- [ ] `apps/edge/internal/bootstrap/single_request_observation_test.go` — assert wiring and failure isolation.
- [ ] `apps/edge/internal/openai/single_request_metrics.go` — preserve ingress ownership and expose bounded test correlation only.
- [ ] `apps/node/internal/workspace/observation.go` — add raw-free Node event projection and safe zap observer.
- [ ] `apps/node/internal/workspace/runtime.go` — emit one tool event at the common completion seam.
- [ ] `apps/node/internal/workspace/cleanup.go` — emit one cleanup event.
- [ ] `apps/node/internal/workspace/observation_test.go` — cover exact key allowlist, sentinel rejection, outcome count, and observer panic/error.

**Test Strategy**

- Gather metrics before and after deterministic flows and inspect captured zap cores. Assert no forbidden keys/values and no request id in metric labels.

**Verification**

- `go test -race ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/node/internal/workspace -run 'Test(SingleRequestMetrics|SingleRequestObservationWiring|WorkspaceObservation)' -count=1`
- Expected: bounded metrics/logs emit once and cannot influence runtime outcomes.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/edge/internal/service/single_request_metrics.go` | API-2 |
| `apps/edge/internal/service/single_request_metrics_test.go` | API-2 |
| `apps/edge/internal/bootstrap/runtime.go` | API-2 |
| `apps/edge/internal/bootstrap/single_request_observation_test.go` | API-2 |
| `apps/edge/internal/openai/single_request_metrics.go` | API-2 |
| `apps/node/internal/workspace/observation.go` | API-2 |
| `apps/node/internal/workspace/runtime.go` | API-2 |
| `apps/node/internal/workspace/cleanup.go` | API-2 |
| `apps/node/internal/workspace/observation_test.go` | API-2 |
| `agent-task/m-iop-owned-single-request-agent-execution/15+14_observation_adapters/CODE_REVIEW-cloud-G08.md` | 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 -race ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/node/internal/workspace -run 'Test(SingleRequestMetrics|SingleRequestObservationWiring|WorkspaceObservation)' -count=1`
3. `go test ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/edge/internal/openai ./apps/node/internal/workspace -count=1`
4. `go vet ./apps/edge/internal/service ./apps/edge/internal/bootstrap ./apps/edge/internal/openai ./apps/node/internal/workspace`
5. `git diff --check`

Expected: packet 14 is uniquely complete; bounded collectors and raw-free Edge/Node logs emit once, observer failures are isolated, and affected packages remain clean. Cached tests are not acceptable.

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