<!-- task=m-node-provider-execution-liveness-recovery/04+03_health_evidence plan=0 tag=API milestone-task=health-classification -->

# PLAN — Node Health Observation Evidence

## For the Implementing Agent

> **MANDATORY:** Do not begin until the dependency below has a PASS `complete.log`. Implement only this checklist, preserve unrelated user changes, and keep edits inside the terminal-evidence slice. Do not update roadmap state, create follow-up plans, commit, push, or run an official code review. Fill `CODE_REVIEW-cloud-G08.md` after implementation and leave active files in place.

## Background

The predecessor watchdog owns the one stall terminal, cancel/close fence, and safe metadata authority. The refined probe-contract child owns exact-target, fail-closed health classification. This dependent child joins those two established boundaries: it sequences finalized observations within the current transport Session and enriches the already-claimed normalized and tunnel terminals only after bounded probe and fence results are both known.

It must not reset progress, extend the watchdog deadline, change confirmed/unconfirmed fence meaning, revive output, retry, or project health at Edge.

## Dependencies

- `agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/complete.log`

The `+03` dependency transitively includes `02+01_stall_watchdog` and `01_activity_contract`. Consume reviewed APIs rather than anticipated names.

## Analysis

### Files Read

- `AGENTS.md`
- target Milestone and approved liveness SDD
- `agent-spec/runtime/edge-node-execution.md`
- `agent-contract/inner/execution-runtime.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `apps/node/internal/transport/session.go`
- `apps/node/internal/transport/session_test.go`
- `apps/node/internal/node/run_handler.go`
- `apps/node/internal/node/tunnel_handler.go`
- predecessor-planned `apps/node/internal/node/liveness_watchdog.go`
- `apps/node/internal/node/runtime_bridge.go`
- `apps/node/internal/node/run_cancel_test.go`
- `apps/node/internal/node/provider_tunnel_test.go`
- `scripts/dev/edge-node-reconnect-diagnostic.sh`

### SDD Criteria

- S03 requires identical safe normalized/tunnel evidence with adapter, exact target, and a monotonic observation sequence scoped to the current connection.
- Probe success is not progress on the original request. Classification must not alter terminal count, fence, retryability, or cleanup.
- Edge reception-generation binding, stale rejection, runtime overlay, recovery, and selection remain later Epic ownership.

### Verification Context

- Fake clock and channel-controlled predecessor fixtures own temporal assertions; no wall-clock sleeps.
- One local real-process full cycle is required in addition to the auxiliary test-only E2E script.
- No external provider, credentials, migrations, or deployments are required.

### Test Coverage Gaps

- Session has no observation counter reset boundary.
- The predecessor terminal retains unknown health and has no sequence.
- Concurrency tests do not prove unique sequence values across normalized and tunnel attempts.
- No assertion combines bounded probe and close-fence completion without resetting progress or losing identical wire metadata.

### Split Judgment

- Large/indivisible: Session sequencing, concurrent probe/fence join, exactly-once terminal authority, and normalized/tunnel variants are one temporal consistency boundary.
- This is the second and final child from one refine-plans application; no further split has an independent PASS state.
- Write overlap with both predecessors is serialized by the explicit dependency chain.

### Scope Rationale

- In scope: Session counter, one sequence per finalized observation, bounded concurrent result join, normalized/tunnel metadata enrichment, deterministic integration tests, contracts/spec.
- Out of scope: adapter prober behavior, activity timer rules, fence/retry ownership changes, Edge overlay/generation binding, recovery, metrics, and configuration.

### Final Routing

- `evaluation_mode=isolated-reassessment`; pair finalizer.
- Build score `scope=2,state=2,blast=1,evidence=1,verification=2` -> cloud G08 `PLAN-cloud-G08.md` by risk boundary.
- Loop risks: `temporal_state`, `concurrent_consistency`, `boundary_contract`, `variant_product` (`count=4`).
- Review is official-review cloud G08 in `CODE_REVIEW-cloud-G08.md`.

## Implementation Checklist

- [ ] [API-1] Add one connection-scoped atomic health-observation sequence source.
- [ ] [API-2] Enrich the already-claimed normalized and tunnel stall terminals after bounded probe/fence completion.
- [ ] [TEST-1] Prove sequence scope, concurrency, terminal invariants, metadata parity, and no progress reset.
- [ ] [DOC-1] Update execution/wire contracts and the matching execution spec without claiming Edge projection.
- [ ] Run every command in Final Verification and record exact results in `CODE_REVIEW-cloud-G08.md`.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Connection-scoped observation sequence

Add an atomic `uint64` counter to `transport.Session`. A new Session starts at zero and its first finalized health observation receives one. Normalized and tunnel attempts on the same Session share the source and receive unique, monotonically increasing values under concurrency. Increment exactly once after classification and before terminal send. Internal/nil or unbound Session paths omit `health_observation_seq`; never invent a process-global generation.

**Modified files**

- [ ] `apps/node/internal/transport/session.go`
- [ ] `apps/node/internal/transport/session_test.go`

**Test decision:** Required; sequential/concurrent increments, new-session reset, nil omission, and overflow policy are explicit.

### [API-2] Join bounded evidence without changing terminal ownership

After the predecessor claims a stall, run its fixed close-grace wait and the reviewed health probe concurrently. Wait only for both bounded outcomes; do not extend either bound serially. Then allocate one sequence and build one allowlisted metadata map containing stable failure/classification, idle duration, Node-owned run/attempt identity, fence, adapter, target, and optional sequence.

Use cloned maps for normalized `Failure.Metadata`, normalized `RuntimeEvent.Metadata`, and tunnel ERROR metadata so the existing protobuf mapper preserves the same values without shared mutable aliases. Preserve retryable as `attempt_fence == confirmed`. Provider availability never resets the observer, suppresses the terminal, changes the fence, or starts another attempt. Late provider output remains fenced.

**Modified files**

- [ ] `apps/node/internal/node/liveness_watchdog.go`
- [ ] `apps/node/internal/node/run_handler.go`
- [ ] `apps/node/internal/node/tunnel_handler.go`

**Test decision:** Required for both execution surfaces and every health/fence combination.

### [TEST-1] Temporal and wire evidence

Extend predecessor fixtures to prove: available/request-stalled, valid unavailable/provider-unhealthy, and every unknown branch; independent live probe context after request cancel; probe completion never resets progress; exactly one terminal; identical safe normalized domain/protobuf/tunnel maps; sequence uniqueness on one Session and reset on another; nil omission; unchanged confirmed/unconfirmed retryability and ownership; late output drop. Use manual clocks and channels only.

**Modified files**

- [ ] `apps/node/internal/node/liveness_watchdog_test.go`
- [ ] `apps/node/internal/node/run_cancel_test.go`
- [ ] `apps/node/internal/node/provider_tunnel_test.go`
- [ ] `apps/node/internal/transport/session_test.go`

### [DOC-1] Evidence boundary

Document three-way health evidence, exact identity, connection-scoped sequence semantics, normalized/tunnel parity, secret/raw exclusions, and that probe success is not progress or retry authority. Explicitly leave reception-generation binding, stale validation, Edge health overlay, recovery, and selection to later work.

**Modified files**

- [ ] `agent-contract/inner/execution-runtime.md`
- [ ] `agent-contract/inner/edge-node-runtime-wire.md`
- [ ] `agent-spec/runtime/edge-node-execution.md`

## Modified Files Summary

| Path | Action | Checklist |
|------|--------|-----------|
| `apps/node/internal/transport/session.go` | modify | API-1 |
| `apps/node/internal/transport/session_test.go` | modify | API-1, TEST-1 |
| `apps/node/internal/node/liveness_watchdog.go` | modify predecessor file | API-2 |
| `apps/node/internal/node/run_handler.go` | modify predecessor file | API-2 |
| `apps/node/internal/node/tunnel_handler.go` | modify predecessor file | API-2 |
| `apps/node/internal/node/liveness_watchdog_test.go` | modify predecessor test | TEST-1 |
| `apps/node/internal/node/run_cancel_test.go` | modify | TEST-1 |
| `apps/node/internal/node/provider_tunnel_test.go` | modify | TEST-1 |
| `agent-contract/inner/execution-runtime.md` | modify | DOC-1 |
| `agent-contract/inner/edge-node-runtime-wire.md` | modify | DOC-1 |
| `agent-spec/runtime/edge-node-execution.md` | modify | DOC-1 |
| `agent-task/m-node-provider-execution-liveness-recovery/04+03_health_evidence/CODE_REVIEW-cloud-G08.md` | update evidence | all |

## Final Verification

1. `go version && go env GOMOD`
2. `go test -count=1 ./packages/go/execution ./packages/go/streamgate ./packages/go/config`
3. `go test -count=1 ./packages/go/execution ./apps/node/...`
4. `go test -count=10 ./apps/node/internal/node ./apps/node/internal/transport`
5. `go test -race -count=3 ./packages/go/execution ./apps/node/internal/node ./apps/node/internal/transport`
6. `go vet ./packages/go/execution ./apps/node/internal/node ./apps/node/internal/transport`
7. `go test -count=1 ./...`
8. `./scripts/e2e-smoke.sh`
9. `IOP_DEV_RECONNECT_BIND_TIMEOUT=45 ./scripts/dev/edge-node-reconnect-diagnostic.sh`
10. `make readability-audit`
11. `git diff --check`

Record exact results in the review stub. A deterministic/race failure is a blocker; do not substitute live-provider smoke.

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