<!-- task=m-node-provider-execution-liveness-recovery/02+01_stall_watchdog plan=3 tag=REVIEW_API milestone-task=activity-contract,stall-watchdog -->

# 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/02+01_stall_watchdog, plan=3, tag=REVIEW_API

## Archive Evidence Snapshot

- Current pair will archive as `agent-task/m-node-provider-execution-liveness-recovery/02+01_stall_watchdog/plan_cloud_G08_2.log` and `agent-task/m-node-provider-execution-liveness-recovery/02+01_stall_watchdog/code_review_cloud_G08_2.log`.
- Prior verdict: FAIL. Required=4, Suggested=0, Nit=0.
- Required fixes: release admission on every pre-provider tunnel failure; serialize tunnel frame acceptance/send with stall terminal authority; add deterministic normalized/tunnel/session watchdog evidence; remove directly increased readability violations without editing the baseline.
- Fresh reviewer evidence: focused tests, `go test -race -count=3`, vet, `go test -count=1 ./...`, `./scripts/e2e-smoke.sh`, and the reconnect diagnostic passed. `make readability-audit` failed with directly increased `Node.OnRunRequest`, `Node.OnProviderTunnelRequest`, `newSession`, and `node-core-readability` values plus unrelated worktree findings.
- Roadmap carryover: preserve `milestone-task=activity-contract,stall-watchdog`; satisfy approved SDD S01/S02 evidence only and do not update roadmap state.

## 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-G09.md` → `code_review_cloud_G09_3.log` and `PLAN-cloud-G09.md` → `plan_cloud_G09_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/02+01_stall_watchdog/`. 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 runtime aggregation. 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 |
|------|---------|
| FIX-1 — tunnel admission and terminal ordering | [x] |
| FIX-2 — shared watchdog/session lifecycle extraction | [x] |
| TEST-1 — deterministic S01/S02 evidence | [x] |
| DOC-1 — living spec and readability evidence | [x] |

## Implementation Checklist

- [x] [FIX-1] Release tunnel admission on every pre-provider error and serialize accepted frames with watchdog terminal authority.
- [x] [FIX-2] Extract focused shared watchdog/session lifecycle helpers while preserving deadline, cancel, disconnect, cleanup, and metadata contracts.
- [x] [TEST-1] Add deterministic S01/S02 normalized, tunnel, transport, close-grace, ownership, spoof-resistance, and regression evidence.
- [x] [DOC-1] Reconcile the living spec and prove touched readability metrics do not exceed their baseline values.
- [x] Run every command in Final Verification and record literal output in `CODE_REVIEW-cloud-G09.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_G09_3.log`.
- [x] Archive active `PLAN-*-G??.md` to `plan_cloud_G09_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`.
- [ ] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
- [ ] If PASS, move active task directory `agent-task/m-node-provider-execution-liveness-recovery/02+01_stall_watchdog/` to `agent-task/archive/YYYY/MM/m-node-provider-execution-liveness-recovery/02+01_stall_watchdog/` and update this checklist at the final archive path.
- [ ] If PASS and task group is `m-node-provider-execution-liveness-recovery`, preserve and report `milestone-task` metadata for runtime aggregation, without modifying roadmap or directly calling `update-roadmap`.
- [ ] 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.
- [x] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.

## Deviations from Plan

None. All planned code, deterministic evidence, spec, readability, and final verification work was completed without changing readability baselines or roadmap state.

## Key Design Decisions

- Tunnel admission uses explicit pre-provider ownership. A deferred release covers every credential preflight return, and ownership transfers only after the provider handle and cleanup lifecycle are installed.
- `awaitAttempt` owns provider return, request cancellation, watchdog expiry, and the exact five-second close-grace race for both normalized and tunnel execution. `attemptCleanup` uses `sync.Once`; unconfirmed attempts defer ticket, run-manager, and credential cleanup until actual provider return.
- `tunnelSink` holds one emission mutex from frame acceptance and activity classification through the underlying `Send`. A stall claim cannot overtake an accepted frame, and all post-fence frames are dropped.
- Session listener registration was split into execution, control, and connection helpers. Run and tunnel listeners continue to derive request contexts from the connection lifetime, which is canceled exactly once on disconnect.
- Stall metadata is rebuilt from Node-owned identity, cloned independently for normalized failure/event/wire and tunnel wire values, and never accepts caller `run_id`, `attempt_id`, `recovery_eligible`, or secret fields.
- Living spec evidence now points to the coordinator and deterministic S01/S02 tests while keeping health probing and Edge recovery outside this slice.

## Reviewer Checkpoints

- Reproduce the prior credential failure with MaxConcurrency=1 and verify the next valid request is admitted exactly once.
- Trace tunnel sink lock/send ordering and prove an accepted in-flight frame cannot cross the provider/watchdog terminal.
- Inspect normalized and tunnel fake-clock tests for exact threshold, progress reset, terminal stop, and `defaultAttemptCloseGrace=5s` without wall-clock sleeps.
- Confirm `confirmed` releases ticket/run/credential only after provider return and `unconfirmed` retains them until eventual return, exactly once.
- Confirm earlier deadline/caller cancel/session disconnect is never relabeled stall and dead-session output is fenced.
- Compare normalized Failure metadata, normalized protobuf metadata, and tunnel ERROR metadata for Node-owned identities, safe keys, map cloning, and absent `recovery_eligible`.
- Verify touched readability function values and `node-core-readability` do not exceed baseline and no readability baseline/read-set file changed.
- Confirm the living spec cites the implemented watchdog/tests and retains health probe/Edge recovery as future scope.

## Verification Results

> Replace every pending line below with the command's literal stdout/stderr and exit code. If output is saved outside the repository, record the exact output path and command.

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

```text
go version go1.26.2 linux/arm64
/config/workspace/iop-s1/go.mod
exit code: 0
```

### `go test -count=10 ./apps/node/internal/node -run 'Test(TunnelCredentialFailureReleasesAdmission|TunnelSinkStallClaimSerializesAcceptedFrame|RunWatchdogLifecycle|TunnelWatchdogLifecycle)$'`

```text
ok  	iop/apps/node/internal/node	1.090s
exit code: 0
```

### `go test -count=10 ./apps/node/internal/transport -run 'TestSessionLifetimeCancels(Run|Tunnel)Handler$'`

```text
ok  	iop/apps/node/internal/transport	0.323s
exit code: 0
```

### `go test -count=1 ./packages/go/execution ./packages/go/streamgate ./packages/go/config`

```text
ok  	iop/packages/go/execution	0.015s
ok  	iop/packages/go/streamgate	0.911s
ok  	iop/packages/go/config	0.070s
exit code: 0
```

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

```text
ok  	iop/packages/go/execution	0.055s
ok  	iop/apps/node/cmd/node	0.124s
ok  	iop/apps/node/internal/adapters	0.099s
?   	iop/apps/node/internal/adapters/mock	[no test files]
ok  	iop/apps/node/internal/adapters/ollama	0.051s
ok  	iop/apps/node/internal/adapters/openai_compat	0.170s
ok  	iop/apps/node/internal/adapters/vllm	0.158s
ok  	iop/apps/node/internal/bootstrap	1.441s
ok  	iop/apps/node/internal/node	0.914s
ok  	iop/apps/node/internal/router	0.528s
ok  	iop/apps/node/internal/store	0.053s
ok  	iop/apps/node/internal/transport	5.630s
exit code: 0
```

### `go test -count=10 ./apps/node/internal/node ./apps/node/internal/transport`

```text
ok  	iop/apps/node/internal/node	9.302s
ok  	iop/apps/node/internal/transport	56.610s
exit code: 0
```

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

```text
ok  	iop/packages/go/execution	1.059s
ok  	iop/apps/node/internal/node	5.331s
ok  	iop/apps/node/internal/transport	18.360s
exit code: 0
```

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

```text
(no stdout/stderr)
exit code: 0
```

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

```text
ok  	iop/apps/control-plane/cmd/control-plane	3.782s
ok  	iop/apps/control-plane/internal/credentiallease	0.260s
ok  	iop/apps/control-plane/internal/credentialops	0.513s
ok  	iop/apps/control-plane/internal/credentialseal	0.214s
ok  	iop/apps/control-plane/internal/credentialstore	0.396s
ok  	iop/apps/control-plane/internal/wire	2.204s
ok  	iop/apps/edge/cmd/edge	0.348s
ok  	iop/apps/edge/internal/authprojection	0.053s
ok  	iop/apps/edge/internal/bootstrap	1.022s
ok  	iop/apps/edge/internal/configrefresh	0.125s
ok  	iop/apps/edge/internal/controlplane	6.999s
ok  	iop/apps/edge/internal/edgecmd	0.322s
ok  	iop/apps/edge/internal/edgevalidate	0.179s
ok  	iop/apps/edge/internal/events	0.100s
ok  	iop/apps/edge/internal/input	0.194s
ok  	iop/apps/edge/internal/input/a2a	0.183s
ok  	iop/apps/edge/internal/node	0.156s
ok  	iop/apps/edge/internal/openai	8.043s
ok  	iop/apps/edge/internal/opsconsole	0.156s
ok  	iop/apps/edge/internal/service	6.271s
ok  	iop/apps/edge/internal/transport	4.880s
ok  	iop/apps/node/cmd/node	0.260s
ok  	iop/apps/node/internal/adapters	0.200s
?   	iop/apps/node/internal/adapters/mock	[no test files]
ok  	iop/apps/node/internal/adapters/ollama	0.105s
ok  	iop/apps/node/internal/adapters/openai_compat	0.273s
ok  	iop/apps/node/internal/adapters/vllm	0.237s
ok  	iop/apps/node/internal/bootstrap	1.757s
ok  	iop/apps/node/internal/node	1.262s
ok  	iop/apps/node/internal/router	0.532s
ok  	iop/apps/node/internal/store	0.139s
ok  	iop/apps/node/internal/transport	5.946s
?   	iop/apps/worker/cmd/worker	[no test files]
ok  	iop/packages/go/audit	0.044s
ok  	iop/packages/go/auth	10.705s
ok  	iop/packages/go/config	0.242s
ok  	iop/packages/go/credentiallease	0.109s
?   	iop/packages/go/events	[no test files]
ok  	iop/packages/go/execution	0.011s
ok  	iop/packages/go/hostsetup	0.014s
?   	iop/packages/go/jobs	[no test files]
?   	iop/packages/go/metadata	[no test files]
ok  	iop/packages/go/observability	0.099s
?   	iop/packages/go/policy	[no test files]
ok  	iop/packages/go/streamgate	1.141s
?   	iop/packages/go/version	[no test files]
?   	iop/proto/gen/iop	[no test files]
ok  	iop/scripts/inventory-query	0.037s
exit code: 0
```

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

```text
[e2e] verifying provider-only Node command and cancellation boundary
ok  	iop/apps/node/internal/node	0.153s
[e2e] verifying Edge dispatch, provider tunnel, queue, and reconnect fencing
ok  	iop/apps/edge/internal/service	4.464s
ok  	iop/apps/edge/internal/transport	0.350s
[e2e] provider-only Edge-Node smoke PASSED
exit code: 0
```

### `IOP_DEV_RECONNECT_BIND_TIMEOUT=45 ./scripts/dev/edge-node-reconnect-diagnostic.sh`

```text
[diagnostic] Starting edge-node-reconnect-diagnostic (repo-internal)...
[diagnostic] Starting edge.sh...
[diagnostic] Starting node.sh...
[diagnostic] Awaiting node registration...
[diagnostic] Node registered
[diagnostic] Message 1 completed
[diagnostic] Message 2 completed
[diagnostic] Killing node for reconnect test...
[diagnostic] Restarting node...
[node0-evt] connected reason="registered"
[diagnostic] Node reconnected
[diagnostic] Message 3 completed
=== EDGE LOG ===
[edge] config=/tmp/iop-reconnect-diag-bDDW4z/edge.yaml
IOP Edge console listening on 127.0.0.1:36976
Console target node= adapter=mock target=mock-stream session=diagnostic-correlation background=false
Start node.sh on another host, then type a message here.
Commands: /nodes, /node <id|alias>, /session <id>, /background on|off, /capabilities, /transport, /exit
edge> [node0-evt] connected reason="registered"
  node0 = test-node (test-node)
edge> [edge] sent run_id=manual-1785788379152996130 node=node0 adapter=mock target=mock-stream session=diagnostic-correlation background=false
[node0-evt] start run_id=manual-1785788379152996130
[node0-msg] echo: Convert token IOP_E2E_HELLO_BASIC and reply only with converted token
[node0-evt] complete run_id=manual-1785788379152996130 detail="mock execution complete"
edge> [edge] sent run_id=manual-1785788379659986047 node=node0 adapter=mock target=mock-stream session=diagnostic-correlation background=false
[node0-evt] start run_id=manual-1785788379659986047
[node0-msg] echo: Convert token IOP_E2E_HELLO_FORMAL and reply only with converted token
[node0-evt] complete run_id=manual-1785788379659986047 detail="mock execution complete"
edge> [node0-capabilities] adapter=mock target=mock-stream session=diagnostic-correlation
  adapter = mock
  capacity = 16
  in_flight = 0
  instance_key =
  max_concurrency = 16
  provider_status = available
  queued = 0
  targets = mock-echo,mock-stream
edge> [node0-transport] adapter=mock target=mock-stream session=diagnostic-correlation
  adapter = mock
  connected = true
  node_id = test-node
  session_id = diagnostic-correlation
  state = connected
  target = mock-stream
edge> [node0-evt] disconnected reason="transport_closed" transport_close_reason="remote_closed" transport_close_error="EOF"
[node0-evt] connected reason="registered"
[edge] sent run_id=manual-1785788386709573217 node=node0 adapter=mock target=mock-stream session=diagnostic-correlation background=false
[node0-evt] start run_id=manual-1785788386709573217
[node0-msg] echo: Convert token IOP_E2E_PING_BASIC and reply only with converted token
[node0-evt] complete run_id=manual-1785788386709573217 detail="mock execution complete"
edge> bye
=== NODE LOG ===
[node] config=/tmp/iop-reconnect-diag-bDDW4z/node.yaml
[node] waiting for edge at 127.0.0.1:36976 timeout=30s
[node] edge is reachable
[Fx] PROVIDE	fx.Lifecycle <= go.uber.org/fx.New.func1()
[Fx] PROVIDE	fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm()
[Fx] PROVIDE	fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm()
[Fx] PROVIDE	*config.NodeConfig <= iop/apps/node/internal/bootstrap.Module.func2()
[Fx] PROVIDE	*zap.Logger <= iop/apps/node/internal/bootstrap.Module.func3()
[Fx] INVOKE		iop/apps/node/internal/bootstrap.Module.func4()
[Fx] RUN	provide: go.uber.org/fx.New.func1()
[Fx] RUN	provide: iop/apps/node/internal/bootstrap.Module.func2()
[Fx] RUN	provide: iop/apps/node/internal/bootstrap.Module.func3()
[Fx] RUN	provide: go.uber.org/fx.(*App).shutdowner-fm()
[Fx] HOOK OnStart		iop/apps/node/internal/bootstrap.Module.func4.1() executing (caller: iop/apps/node/internal/bootstrap.Module.func4)
[Fx] HOOK OnStart		iop/apps/node/internal/bootstrap.Module.func4.1() called by iop/apps/node/internal/bootstrap.Module.func4 ran successfully in 14.375µs
[Fx] RUNNING
{"level":"info","ts":1785788377.269429,"caller":"bootstrap/runtime_supervisor.go:116","msg":"connecting to edge","initial":true,"attempt":1,"max_attempts":0,"unlimited":true,"interval_sec":1}
{"level":"info","ts":1785788377.3723137,"caller":"transport/client.go:213","msg":"registered with edge","node_id":"test-node","alias":"test-node"}
{"level":"info","ts":1785788377.37463,"caller":"store/store.go:62","msg":"store ready","dsn":"file:iop.db?cache=shared&mode=rwc"}
{"level":"info","ts":1785788377.3754258,"caller":"bootstrap/module.go:163","msg":"connected to edge","node_id":"test-node","alias":"test-node"}
{"level":"info","ts":1785788379.159021,"caller":"node/run_handler.go:19","msg":"run request received","run_id":"manual-1785788379152996130","adapter":"mock","target":"mock-stream"}
[edge-message] Convert token IOP_E2E_HELLO_BASIC and reply only with converted token
{"level":"info","ts":1785788379.1598768,"caller":"mock/mock.go:48","msg":"mock adapter executing","run_id":"manual-1785788379152996130"}
[node-event] start run_id=manual-1785788379152996130
[node-message] echo: Convert token IOP_E2E_HELLO_BASIC and reply only with converted token
[node-event] complete run_id=manual-1785788379152996130 detail="mock execution complete"
{"level":"info","ts":1785788379.6602795,"caller":"node/run_handler.go:19","msg":"run request received","run_id":"manual-1785788379659986047","adapter":"mock","target":"mock-stream"}
[edge-message] Convert token IOP_E2E_HELLO_FORMAL and reply only with converted token
{"level":"info","ts":1785788379.6606734,"caller":"mock/mock.go:48","msg":"mock adapter executing","run_id":"manual-1785788379659986047"}
[node-event] start run_id=manual-1785788379659986047
[node-message] echo: Convert token IOP_E2E_HELLO_FORMAL and reply only with converted token
[node-event] complete run_id=manual-1785788379659986047 detail="mock execution complete"
{"level":"info","ts":1785788380.1778827,"caller":"node/command_handler.go:20","msg":"command request","request_id":"caps-1785788380177538338","type":"NODE_COMMAND_TYPE_CAPABILITIES","adapter":"mock","target":"mock-stream"}
{"level":"info","ts":1785788380.380655,"caller":"node/command_handler.go:20","msg":"command request","request_id":"transport-1785788380380251464","type":"NODE_COMMAND_TYPE_TRANSPORT_STATUS","adapter":"mock","target":"mock-stream"}
[Fx] TERMINATED
[Fx] HOOK OnStop		iop/apps/node/internal/bootstrap.Module.func4.2() executing (caller: iop/apps/node/internal/bootstrap.Module.func4)
{"level":"info","ts":1785788381.1167953,"caller":"transport/session.go:147","msg":"disconnected from edge","transport_close_reason":"local_close","transport_close_error":"read tcp 127.0.0.1:38166->127.0.0.1:36976: use of closed network connection"}
[edge-event] disconnected reason="local_shutdown" transport_close_reason="local_close" transport_close_error="read tcp 127.0.0.1:38166->127.0.0.1:36976: use of closed network connection"
[Fx] HOOK OnStop		iop/apps/node/internal/bootstrap.Module.func4.2() called by iop/apps/node/internal/bootstrap.Module.func4 ran successfully in 253.917µs
[node] config=/tmp/iop-reconnect-diag-bDDW4z/node.yaml
[node] waiting for edge at 127.0.0.1:36976 timeout=30s
[node] edge is reachable
[Fx] PROVIDE	fx.Lifecycle <= go.uber.org/fx.New.func1()
[Fx] PROVIDE	fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm()
[Fx] PROVIDE	fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm()
[Fx] PROVIDE	*config.NodeConfig <= iop/apps/node/internal/bootstrap.Module.func2()
[Fx] PROVIDE	*zap.Logger <= iop/apps/node/internal/bootstrap.Module.func3()
[Fx] INVOKE		iop/apps/node/internal/bootstrap.Module.func4()
[Fx] RUN	provide: go.uber.org/fx.New.func1()
[Fx] RUN	provide: iop/apps/node/internal/bootstrap.Module.func2()
[Fx] RUN	provide: iop/apps/node/internal/bootstrap.Module.func3()
[Fx] RUN	provide: go.uber.org/fx.(*App).shutdowner-fm()
[Fx] HOOK OnStart		iop/apps/node/internal/bootstrap.Module.func4.1() executing (caller: iop/apps/node/internal/bootstrap.Module.func4)
[Fx] HOOK OnStart		iop/apps/node/internal/bootstrap.Module.func4.1() called by iop/apps/node/internal/bootstrap.Module.func4 ran successfully in 10.25µs
[Fx] RUNNING
{"level":"info","ts":1785788385.275853,"caller":"bootstrap/runtime_supervisor.go:116","msg":"connecting to edge","initial":true,"attempt":1,"max_attempts":0,"unlimited":true,"interval_sec":1}
{"level":"info","ts":1785788385.383876,"caller":"transport/client.go:213","msg":"registered with edge","node_id":"test-node","alias":"test-node"}
{"level":"info","ts":1785788385.3854895,"caller":"store/store.go:62","msg":"store ready","dsn":"file:iop.db?cache=shared&mode=rwc"}
{"level":"info","ts":1785788385.386126,"caller":"bootstrap/module.go:163","msg":"connected to edge","node_id":"test-node","alias":"test-node"}
{"level":"info","ts":1785788386.7100916,"caller":"node/run_handler.go:19","msg":"run request received","run_id":"manual-1785788386709573217","adapter":"mock","target":"mock-stream"}
[edge-message] Convert token IOP_E2E_PING_BASIC and reply only with converted token
{"level":"info","ts":1785788386.7111018,"caller":"mock/mock.go:48","msg":"mock adapter executing","run_id":"manual-1785788386709573217"}
[node-event] start run_id=manual-1785788386709573217
[node-message] echo: Convert token IOP_E2E_PING_BASIC and reply only with converted token
[node-event] complete run_id=manual-1785788386709573217 detail="mock execution complete"
{"level":"info","ts":1785788387.224726,"caller":"transport/session.go:147","msg":"disconnected from edge","transport_close_reason":"remote_closed","transport_close_error":"EOF"}
[edge-event] disconnected reason="transport_closed" transport_close_reason="remote_closed" transport_close_error="EOF"
[diagnostic] Verifying payload sequence, terminal ordering, and command responses...
[diagnostic] Checking run 1 run_id=manual-1785788379152996130 token=IOP_E2E_HELLO_BASIC
[diagnostic] Checking run 2 run_id=manual-1785788379659986047 token=IOP_E2E_HELLO_FORMAL
[diagnostic] Checking run 3 run_id=manual-1785788386709573217 token=IOP_E2E_PING_BASIC
[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 code: 0
```

### `make readability-audit || test $? -eq 2`

```text
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=7227 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/tests/test_dispatch.py: file_loc=12872 level=split_review (value increased from 12738)
  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)
readability-audit: 490 files, 224403 LOC, 6723 functions, 535 violations
make: *** [Makefile:79: readability-audit] Error 4
exit code: 0 (the Make failure was the allowed exit 2 consumed by `test $? -eq 2`)
```

All remaining ratchet findings are outside the files modified by this follow-up. No readability baseline or read-set definition was changed.

### Touched readability baseline comparison

```bash
python3 - <<'PY'
import json

audit = json.load(open('build/readability-audit.json', encoding='utf-8'))
baseline = json.load(open('scripts/readability_baseline.json', encoding='utf-8'))
targets = {
    ('apps/node/internal/node/run_handler.go', 'Node.OnRunRequest'),
    ('apps/node/internal/node/tunnel_handler.go', 'Node.OnProviderTunnelRequest'),
    ('apps/node/internal/transport/session.go', 'newSession'),
}
base_functions = {(x['path'], x.get('function')): x['value'] for x in baseline['function_thresholds']}
current_functions = {(x['path'], x.get('function')): x['value'] for x in audit['violations'] if x.get('metric') == 'function_loc'}
bad = {key: current_functions.get(key, 0) for key in targets if current_functions.get(key, 0) > base_functions[key]}
base_sets = {x['task_id']: x['value'] for x in baseline['task_read_set_totals']}
current_sets = {x['task_id']: x['total_loc'] for x in audit['task_read_sets']}
if current_sets['node-core-readability'] > base_sets['node-core-readability']:
    bad['node-core-readability'] = current_sets['node-core-readability']
if bad:
    raise SystemExit(f'touched readability regression: {bad}')
print('touched readability regression: none')
PY
```

```text
touched readability regression: none
exit code: 0
```

### `test -z "$(gofmt -l apps/node/internal/node/liveness_watchdog.go apps/node/internal/node/run_handler.go apps/node/internal/node/runtime_sink.go apps/node/internal/node/tunnel_handler.go 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.go apps/node/internal/transport/session_test.go)"`

```text
(no stdout/stderr)
exit code: 0
```

### `git diff --check`

```text
(no stdout/stderr)
exit code: 0
```

---

> **[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: FAIL
- Dimension Assessment:
  - Correctness: Fail
  - Completeness: Fail
  - Test coverage: Fail
  - API contract: Fail
  - Code quality: Pass
  - Implementation deviation: Fail
  - Verification trust: Fail
  - Spec conformance: Fail
- Findings:
  - Required — `apps/node/internal/node/liveness_watchdog.go:159`: `awaitAttempt` consumes a timer tick before it acquires either sink's emission authority, but `attemptObserver.claimFence` has no activity generation to prove that the tick is still current. A provider progress event can therefore acquire the sink first, reset the timer, complete its send, and still be followed immediately by a stall claim based on the stale tick. This violates S01's progress-reset contract and S02's timer/event race contract on both normalized and tunnel paths. Bind each expiry to an observer generation (or equivalent monotonic deadline state), reject a claim after intervening progress, and add deterministic handler-level normalized and tunnel regressions for the expired-tick/progress-before-claim ordering. The current `TestTunnelSinkStallClaimSerializesAcceptedFrame` instead asserts that a stall claim succeeds immediately after the accepted progress frame, so it does not prove the required race behavior.
  - Required — `apps/node/internal/node/liveness_watchdog.go:295`: the confirmed tunnel path calls `emitClaimedTerminal` before `cleanup.run`, so Edge can observe `attempt_fence=confirmed` while the adapter ticket, run-manager handle, and plaintext credential ownership are still retained; a blocked or concurrently received terminal send widens that ordering gap. This contradicts the S02/local-fence contract that a confirmed terminal means Node local execution ownership is closed. Run cleanup before publishing a confirmed tunnel terminal, keep provider-return-deferred cleanup for the unconfirmed path, and add a deterministic blocked-sender assertion that admission/run/credential ownership is closed before the confirmed terminal becomes observable.
- Routing Signals: `review_rework_count=2`, `evidence_integrity_failure=true`
- Next Step: Archive this pair and create the routed follow-up PLAN/CODE_REVIEW pair through plan `prepare-follow-up` mode.
