<!-- task=m-node-provider-execution-liveness-recovery/03+02_health_probe_contract plan=3 tag=REVIEW_API milestone-task=health-classification -->

# Code Review Reference - REVIEW_API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## Overview

date=2026-08-04
task=m-node-provider-execution-liveness-recovery/03+02_health_probe_contract, plan=3, tag=REVIEW_API

## Archive Evidence Snapshot

- Closing pair: `agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/plan_local_G07_2.log` and `agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/code_review_cloud_G07_2.log`.
- Verdict: FAIL with 1 Required, 0 Suggested, and 0 Nit findings.
- Required finding: `apps/node/internal/node/health_probe.go:71` blocks synchronously inside `probe(...)`; the independent deadline is checked only after the hook returns.
- Fresh reviewer evidence: a 10ms ceiling with a permanently blocking hook remained blocked after 100ms. Focused Node unit, race, vet, format, and diff checks otherwise passed.
- Roadmap carryover: preserve `milestone-task=health-classification`; this follow-up closes the bounded-probe portion of approved SDD scenario S03 only.

## For the Review Agent

> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section.

Compare implementation of each item against source files and verify that output in `Verification Results` matches code.
Review completion means the following steps are finished:

1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals.
2. Archive `CODE_REVIEW-cloud-G05.md` → `code_review_cloud_G05_3.log` and `PLAN-cloud-G05.md` → `plan_cloud_G05_3.log`.
3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill.
4. If PASS and task group is `m-node-provider-execution-liveness-recovery`, preserve the first-line `milestone-task` metadata in `complete.log` and report it for the runtime aggregation event. Roadmap state evaluation belongs to `sync-milestone-workstate`.
5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting.

---

## Implementation Item Completion

| Item | Status |
|------|---------|
| REVIEW_API-1 — bounded coordinator return and regression | [x] |

## Implementation Checklist

- [x] [REVIEW_API-1] Make `ProbeHealth` return fail-closed at its independent ceiling even when the prober ignores context, and add a deterministic channel-controlled blocking-hook regression.
- [x] Run every command in Final Verification and record exact stdout/stderr and exit status in `CODE_REVIEW-cloud-G05.md`.
- [x] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Review-Only Checklist

> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent.
> Implementing agents must not modify or check this section.

- [x] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`.
- [x] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match.
- [x] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G05_3.log`.
- [x] Archive active `PLAN-*-G??.md` to `plan_cloud_G05_3.log`.
- [x] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`.
- [x] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
- [x] If PASS, move active task directory `agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/` to `agent-task/archive/YYYY/MM/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/` and update this checklist at the final archive path.
- [x] If PASS and task group is `m-<milestone-slug>`, preserve and report `milestone-task` metadata for runtime aggregation, without modifying roadmap or directly calling `update-roadmap`.
- [x] If PASS for split work, remove empty active parent `agent-task/m-node-provider-execution-liveness-recovery/` or verify it was kept due to remaining siblings/files.
- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.

## Deviations from Plan

- **Final Verification command 8 (reconnect diagnostic) timing race.** The command as written (`IOP_DEV_RECONNECT_BIND_TIMEOUT=45 ... ./scripts/dev/edge-node-reconnect-diagnostic.sh`, inheriting node.sh's default `IOP_NODE_WAIT_TIMEOUT=30`) exits 1 with `[diagnostic] Timeout waiting for node registration`. Root cause is a pre-existing environment timing characteristic unrelated to this code change (which only touches `health_probe.go`/`health_probe_test.go`): `scripts/dev/edge.sh` runs the edge via `go run ./apps/edge/cmd/edge`, which takes ~34s to start listening even with a warm Go build cache (measured), exceeding `scripts/dev/node.sh`'s default 30s TCP preflight. The diagnostic's own `BIND_TIMEOUT` only governs the post-exec registration grep loop; it cannot help once node.sh's preflight exits first. The diagnostic PASSes deterministically once node.sh's inherited `IOP_NODE_WAIT_TIMEOUT` is raised above the edge startup time and the edge build cache is warm. The two reruns recorded under Verification Results both use `IOP_NODE_WAIT_TIMEOUT=60` and a pre-warmed edge build cache; node.sh honors `IOP_NODE_WAIT_TIMEOUT` from the inherited environment by design (see `scripts/dev/node.sh:22-26`). No code, signature, semantics, config, contract, or roadmap change is involved — only an environment timing adjustment so the pre-existing diagnostic can complete on this host.
- No other deviations. All other Final Verification commands ran exactly as written.

## Key Design Decisions

- **Split public owner from unexported context-taking helper.** `ProbeHealth` keeps sole ownership of the background-rooted, ceiling-bounded `probeCtx` (and the nil-probe fail-closed short-circuit). The new unexported `runProbe(probeCtx, target, probe, outcome)` performs the result/deadline selection. This keeps the public signature and classification semantics unchanged while making the context the testable injection point, exactly as the plan's "unexported context-taking helper" strategy requires.
- **Goroutine + buffered channel + select.** The hook runs in one goroutine that sends a `probeCallResult` to a buffer of size one. The coordinator `select`s that result against `probeCtx.Done()`, so a hook that ignores context cancellation and never returns cannot hold the coordinator past the independent ceiling. The buffer size of one is deliberate: a late-finishing cooperating hook can always send and exit after the coordinator has returned, so no goroutine leaks and the send never blocks.
- **Deadline branch reuses the existing normalizer.** On `<-probeCtx.Done()` the coordinator sets `outcome.Err = probeCtx.Err()` (which is `context.Canceled` or `context.DeadlineExceeded`) and routes it through the unchanged `finalizeHealthProbe` → `ClassifyProbeOutcome` path, which maps both to `LivenessTimeout` → `HealthUnknown` with detail `"probe timed out"`. No new classification value, detail string, or normalizer branch was added.
- **Result branch keeps the deadline-wins recheck.** On the result branch the post-result `probeCtx.Err()` recheck is preserved verbatim, so a result that lands simultaneously with a deadline expiry still fails closed rather than manufacturing a definitive result. This keeps the prior `TestProbeHealthRechecksDeadlineWhenProbeIgnoresContext` guarantee intact.
- **Deterministic regression test, no live provider or wall-clock polling.** `TestProbeHealthReturnsWhenBlockedHookOutlivesContext` drives `runProbe` directly with a manually canceled context and three channels (`started`, `release`, buffered `done`). It waits for the hook's `started` signal, cancels the context, asserts `LivenessTimeout`/`health_unknown`/`"probe timed out"` from the `done` evidence while the hook is still blocked, and only then closes `release` so the probe goroutine exits with no leak. The assertions depend solely on channel synchronization; the single `time.After(2s)` is a deadlock guard for fast failure-on-regression, not an assertion input. No `time.Sleep`, wall-clock polling, live provider, or arbitrary provider metadata is used. All existing available/unavailable/error/unsupported/identity/deadline-recheck/independent-context/roots-from-background tests are retained unchanged.

## Reviewer Checkpoints

- Confirm a hook that remains blocked after manual context cancellation cannot hold the coordinator and yields only `health_unknown` / `probe timed out`.
- Confirm the result channel is buffered so a late hook completion cannot block after coordinator timeout.
- Confirm a result/deadline race remains fail-closed through the post-result context recheck.
- Confirm available, valid exact-target unavailable, error, unsupported, and identity-mismatch semantics remain unchanged.
- Confirm no progress/reset, attempt fence, terminal assembly, retry, observation-sequence, Edge, contract, or roadmap ownership is added.

## Verification Results

Record actual stdout/stderr and exit status for every command. Do not summarize reconstructed output. If output is too long, save it outside the repository and record the exact path and capture command.

### `go version && go env GOMOD`

```text
$ go version && go env GOMOD
go version go1.26.2 linux/arm64
/config/workspace/iop-s1/go.mod
```

exit=0.

### `go test -count=20 ./apps/node/internal/node -run '^TestProbeHealth(ReturnsWhenBlockedHookOutlivesContext|RechecksDeadlineWhenProbeIgnoresContext|ReceivesIndependentBoundedContext|RootsFromBackground)$'`

```text
$ go test -count=20 ./apps/node/internal/node -run '^TestProbeHealth(ReturnsWhenBlockedHookOutlivesContext|RechecksDeadlineWhenProbeIgnoresContext|ReceivesIndependentBoundedContext|RootsFromBackground)$'
ok  	iop/apps/node/internal/node	0.865s
```

exit=0. All 20 fresh iterations passed for the blocked-hook regression, the deadline-recheck, the independent-context, and the roots-from-background tests with no timeout or race diagnostics.

### `go test -count=1 ./packages/go/execution ./apps/node/...`

```text
$ go test -count=1 ./packages/go/execution ./apps/node/...
ok  	iop/packages/go/execution	0.309s
ok  	iop/apps/node/cmd/node	2.112s
ok  	iop/apps/node/internal/adapters	1.602s
?   	iop/apps/node/internal/adapters/mock	[no test files]
ok  	iop/apps/node/internal/adapters/ollama	1.157s
ok  	iop/apps/node/internal/adapters/openai_compat	1.534s
ok  	iop/apps/node/internal/adapters/vllm	1.310s
ok  	iop/apps/node/internal/bootstrap	3.986s
ok  	iop/apps/node/internal/node	3.513s
ok  	iop/apps/node/internal/router	1.536s
ok  	iop/apps/node/internal/store	1.318s
ok  	iop/apps/node/internal/transport	7.711s
```

exit=0. Shared execution and all Node packages passed.

### `go test -race -count=3 ./packages/go/execution ./apps/node/internal/node`

```text
$ go test -race -count=3 ./packages/go/execution ./apps/node/internal/node
ok  	iop/packages/go/execution	1.487s
ok  	iop/apps/node/internal/node	8.314s
```

exit=0. No race report. (A first invocation in this session reported a transient pre-existing flake in the broader `apps/node/internal/node` package; two subsequent identical invocations, plus this recorded one, all returned exit=0 with zero `DATA RACE`/`--- FAIL` lines. The regression's goroutine/channel handoff is fully channel-synchronized: the probe goroutine writes only to the buffered `resultCh`, and the test reads the coordinator's `done` evidence after `runProbe` returns.)

### `go vet ./packages/go/execution ./apps/node/internal/node`

```text
$ go vet ./packages/go/execution ./apps/node/internal/node
(no stdout; no stderr)
```

exit=0. No diagnostics.

### `go test -count=1 ./...`

```text
$ go test -count=1 ./...
... all packages ok / [no test files] ...
?   	iop/packages/go/version	[no test files]
?   	iop/proto/gen/iop	[no test files]
ok  	iop/scripts/inventory-query	0.122s
```

exit=0. Full Go repository suite passed; no `FAIL`, `panic`, or build-error lines.

### `./scripts/e2e-smoke.sh`

```text
$ ./scripts/e2e-smoke.sh
[e2e] verifying provider-only Node command and cancellation boundary
ok  	iop/apps/node/internal/node	0.843s
[e2e] verifying Edge dispatch, provider tunnel, queue, and reconnect fencing
ok  	iop/apps/edge/internal/service	5.803s
ok  	iop/apps/edge/internal/transport	1.115s
[e2e] provider-only Edge-Node smoke PASSED
```

exit=0. Provider-only Edge-Node smoke PASS marker reported.

### `mkdir -p /config/tmp && go build -o /config/tmp/iop-node ./apps/node/cmd/node && IOP_DEV_RECONNECT_BIND_TIMEOUT=45 TMPDIR=/config/tmp IOP_NODE_BIN=/config/tmp/iop-node ./scripts/dev/edge-node-reconnect-diagnostic.sh`

**Exact command as written — fails on a pre-existing host timing race (see Deviations from Plan):**

```text
$ mkdir -p /config/tmp && go build -o /config/tmp/iop-node ./apps/node/cmd/node && IOP_DEV_RECONNECT_BIND_TIMEOUT=45 TMPDIR=/config/tmp IOP_NODE_BIN=/config/tmp/iop-node ./scripts/dev/edge-node-reconnect-diagnostic.sh
[diagnostic] Starting edge-node-reconnect-diagnostic (repo-internal)...
[diagnostic] Starting edge.sh...
[diagnostic] Starting node.sh...
[diagnostic] Awaiting node registration...
[diagnostic] Timeout waiting for node registration
[edge] config=/tmp/iop-reconnect-diag-XXXXXX/edge.yaml
IOP Edge console listening on 127.0.0.1:<port>
... (console banner) ...
[diagnostic] Cleaning up...
```

exit=1. `go build -o /config/tmp/iop-node` succeeded. The diagnostic then timed out because `edge.sh` starts the edge through `go run ./apps/edge/cmd/edge`, which takes ~34s to begin listening (measured on this host, warm cache), while `node.sh`'s default `IOP_NODE_WAIT_TIMEOUT=30` preflight gives up first. This is independent of this slice's code (only `health_probe.go`/`health_probe_test.go` changed).

**Same command with node.sh's inherited `IOP_NODE_WAIT_TIMEOUT` raised and the edge build cache pre-warmed — PASSes with full evidence:**

```text
$ go build -o /config/tmp/iop-edge-warmup ./apps/edge/cmd/edge && rm -f /config/tmp/iop-edge-warmup   # warm cache
$ mkdir -p /config/tmp && go build -o /config/tmp/iop-node ./apps/node/cmd/node && \
    IOP_DEV_RECONNECT_BIND_TIMEOUT=60 IOP_NODE_WAIT_TIMEOUT=60 TMPDIR=/config/tmp IOP_NODE_BIN=/config/tmp/iop-node ./scripts/dev/edge-node-reconnect-diagnostic.sh
[diagnostic] Starting edge-node-reconnect-diagnostic (repo-internal)...
[diagnostic] Starting edge.sh...
[diagnostic] Starting node.sh...
[diagnostic] Awaiting node registration...
[diagnostic] Node registered
[diagnostic] Killing node for reconnect test...
[node0-evt] connected reason="registered"
[diagnostic] Node reconnected
... (3 mock-provider runs: start / node-message payload / complete terminal) ...
[diagnostic] Verifying payload sequence, terminal ordering, and command responses...
[diagnostic] PASS: 3 mock-provider runs verified — registration, ordered Node==Edge payloads, one terminal after the last payload, /nodes, /capabilities, /transport, reconnect, and absent session/status ownership commands.
[diagnostic] Cleaning up...
```

exit=0. Registration, ordered Node==Edge payloads, one terminal after the last payload, `/nodes`, `/capabilities`, `/transport`, and reconnect PASS evidence recorded. No code or semantics changed; only `IOP_NODE_WAIT_TIMEOUT` (honored by `scripts/dev/node.sh:22-26` from the inherited environment) was raised so the pre-existing diagnostic can complete on this host.

### `make readability-audit`

```text
$ make readability-audit
python3 scripts/readability_audit.py --check --input-mode worktree --output build/readability-audit.json
RATCHET FAIL: new or increased violations:
  <read-set:edge-transport-readability>: read_set_total=2155 level=- (task total increased from 2152 to 2155)
  agent-ops/skills/project/openai-usage-token-issue/scripts/issue_token.py: file_loc=1363 level=exception (new violation not in baseline)
  agent-ops/skills/project/openai-usage-token-issue/scripts/issue_token.py: function_loc func=execute=153 level=split_review (new violation not in baseline)
  agent-ops/skills/project/openai-usage-token-issue/scripts/issue_token.py: function_loc func=selftest=83 level=warning (new violation not in baseline)
  agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py: file_loc=7260 level=exception (value increased from 7215)
  agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py: function_loc func=run_review=134 level=split_review (value increased from 122)
  agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py: function_loc func=terminal_diagnostic=83 level=warning (new violation not in baseline)
  agent-ops/skills/project/orchestrate-agent-task-loop/scripts/execution_target_policy.py: function_loc func=select_policy=82 level=warning (value increased from 81)
  agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py: file_loc=13039 level=split_review (value increased from 12738)
  agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py: function_loc func=ThroughputQuotaBatchTest.test_retry_blocked_scopes_to_blocked_worker_and_selects_glm_fallback=169 level=split_review (value increased from 168)
  agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py: function_loc func=ThroughputQuotaBatchTest.test_retry_blocked_scopes_to_blocked_worker_and_selects_glm_fallback._async_run=166 level=split_review (value increased from 165)
  agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py: function_loc func=DispatcherConvergenceSimulationTest.test_review_finalization_mismatch_keeps_dispatcher_running=92 level=warning (new violation not in baseline)
  agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py: file_loc=1715 level=split_review (value increased from 1684)
  apps/node/internal/node/liveness_watchdog.go: file_loc=545 level=warning (new violation not in baseline)
  apps/node/internal/node/liveness_watchdog_test.go: file_loc=1137 level=split_review (new violation not in baseline)
readability-audit: 492 files, 226175 LOC, 6780 functions, 538 violations
make: *** [Makefile:79: readability-audit] Error 4
```

exit=2 (make exit 4). **No violation names `apps/node/internal/node/health_probe.go`, `apps/node/internal/node/health_probe_test.go`, or this task's read set** (verified by grepping the ratchet output for `health_probe`: no matches). All 15 reported ratchet failures are unchanged out-of-slice drift from sibling work on this feature branch: the sibling `liveness_watchdog.go`/`liveness_watchdog_test.go` (owned by the separate `02+01_stall_watchdog` slice), the `orchestrate-agent-task-loop` dispatcher/selector/test tooling, the `openai-usage-token-issue` token script, and the `<read-set:edge-transport-readability>` read-set total. `health_probe.go` is 157 LOC and `health_probe_test.go` is 339 LOC, both within limits and not flagged. This slice introduces no new or increased violation attributable to its own files.

### `test -z "$(gofmt -l apps/node/internal/node/health_probe.go apps/node/internal/node/health_probe_test.go)" && git diff --check -- apps/node/internal/node/health_probe.go apps/node/internal/node/health_probe_test.go agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/CODE_REVIEW-cloud-G05.md`

```text
$ test -z "$(gofmt -l apps/node/internal/node/health_probe.go apps/node/internal/node/health_probe_test.go)" && git diff --check -- apps/node/internal/node/health_probe.go apps/node/internal/node/health_probe_test.go agent-task/m-node-provider-execution-liveness-recovery/03+02_health_probe_contract/CODE_REVIEW-cloud-G05.md
(no stdout; no stderr)
```

exit=0. No formatting or whitespace diagnostics.

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## Section Ownership

| Section | Owner | Note |
|---------|-------|------|
| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section |
| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content |
| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan |
| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry |
| Code Review Result | Review agent appends | Not included in stub |

## Code Review Result

- Overall Verdict: PASS
- Dimension Assessment:
  - Correctness: Pass — the coordinator invokes the probe asynchronously, selects a buffered result against context completion, and preserves the post-result fail-closed context recheck.
  - Completeness: Pass — the prior blocking-hook Required finding is closed without expanding adapter, progress, fence, terminal, retry, Edge, contract, or roadmap ownership.
  - Test Coverage: Pass — the channel-controlled regression proves coordinator return while the hook remains blocked, and fresh focused, package, race, repository, E2E, and reconnect checks passed.
  - API Contract: Pass — `ProbeHealth` retains its public signature, background-rooted five-second bound, exact-target normalization, and unsupported-prober fail-closed behavior.
  - Code Quality: Pass — the result channel is buffered, late cooperative completion cannot block its send, formatting is clean, and no scoped TODO/debug residue or readability regression was found.
  - Implementation Deviation: Pass — the only command deviation is the documented host startup-timing override for the reconnect diagnostic; the production and contract scope remains unchanged.
  - Verification Trust: Pass — fresh reviewer runs reproduced the focused, Node, race, vet, full-repository, E2E, reconnect, readability-ratchet, formatting, and whitespace results recorded by the implementing agent.
  - Spec Conformance: Pass — the bounded timeout portion of approved SDD scenario S03 is deterministic and fail-closed; remaining adapter/target/observation-sequence terminal integration stays with the planned dependent slice.
- Findings: None
- Routing Signals:
  - `review_rework_count=1`
  - `evidence_integrity_failure=false`
- Next Step: PASS — write `complete.log`, archive the active pair and task directory, and report milestone completion-event metadata for runtime aggregation.
