<!-- task=control_plane_phase_exit_followups/01_heartbeat_timeout_runtime plan=3 tag=REVIEW_REVIEW_REVIEW_CLOUD_G06 -->

# Follow-up Plan - REVIEW_REVIEW_REVIEW_CLOUD_G06

## Metadata

- date: 2026-06-10
- task: `control_plane_phase_exit_followups/01_heartbeat_timeout_runtime`
- plan: 3
- tag: `REVIEW_REVIEW_REVIEW_CLOUD_G06`
- parent plan log: `plan_cloud_G06_2.log`
- parent review log: `code_review_cloud_G06_2.log`
- verdict source: FAIL follow-up

## Problem

The timeout loop cleanup implementation now calls `stopTimeoutLoop()` from both `Start` and `StartListener`, and core tests pass. The remaining blocker is test completeness: the focused failure-path test covers only `StartListener`/`Serve` with a closed listener. The plan explicitly required direct coverage for `Server.Start()` / `ListenAndServe` failure as well.

## Scope

- Keep existing production code unless the new test exposes a real bug.
- Add only the missing `Start()` listen failure lifecycle test and the corresponding verification evidence.
- Do not modify sibling task files such as `apps/runner/test/oto_iop_connection_smoke_test.dart` or general test rules.
- Do not change runner protocol, HTTP routes, timeout defaults, or job/execution state behavior.

## Implementer Instructions

Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation. If a user-only decision, user-owned external prerequisite, or scope conflict blocks the work, fill the `사용자 리뷰 요청` section in `CODE_REVIEW-cloud-G06.md`, leave the active files in place, and stop for code review.

Evidence gaps that can be closed by rerunning commands or collecting output are normal implementation work, not user-review blockers.

## 구현 항목

### REVIEW_REVIEW_REVIEW_CLOUD_G06-1 - Add Start listen failure lifecycle coverage

Problem: `services/core/internal/httpserver/server_test.go` has `TestServerStartListenerFailureStopsTimeoutLoop`, but no equivalent test for `Server.Start()` when `ListenAndServe` fails before serving.

Solution:

- Add a server-level test in `services/core/internal/httpserver/server_test.go`, for example `TestServerStartFailureStopsTimeoutLoop`.
- Create a deterministic listen failure by binding a local TCP listener, keeping it open, and constructing `NewServerWithConfig(addr, ...)` with the occupied address before calling `server.Start()` in a goroutine.
- Assert that `Start()` returns a non-nil error within a bounded deadline.
- Assert that `Shutdown` or direct `loopDone` observation completes within a bounded deadline after `Start()` returns, proving the timeout loop was cleaned up.
- Keep the existing `StartListener` failure test.

Checklist:

- [ ] `Server.Start()` listen failure is directly covered by a test.
- [ ] The test fails if the timeout loop remains open after `Start()` returns.
- [ ] The test uses bounded waits and does not rely on blind sleeps.
- [ ] Existing `StartListener` failure and shutdown tests still pass.

Intermediate verification:

```bash
cd services/core && go test -count=1 -run 'TestServer(Start|StartListener).*Failure.*TimeoutLoop|TestServerShutdown' -v ./internal/httpserver
```

## 구현 체크리스트

- [ ] [REVIEW_REVIEW_REVIEW_CLOUD_G06-1] `Server.Start()` listen failure lifecycle 테스트를 추가한다.
- [ ] `CODE_REVIEW-cloud-G06.md`에 구현 결과와 검증 출력, 사용자 리뷰 요청 상태를 기록한다.

## Verification

- Required: `cd services/core && go test -count=1 -run 'TestServer(Start|StartListener).*Failure.*TimeoutLoop|TestServerShutdown' -v ./internal/httpserver`
- Required: `cd services/core && go test -count=1 ./...`

## Handoff Notes

- Previous review verification passed, but the command output only showed `TestServerStartListenerFailureStopsTimeoutLoop`, `TestServerShutdownWithoutStartDoesNotHang`, and `TestServerShutdownStopsTimeoutLoop`.
- `rg "TestServerStart.*Failure|TestServerStartListener.*Failure|Start\\(\\)" -n services/core/internal/httpserver/server_test.go services/core/internal/httpserver/server.go` should show both `TestServerStartFailureStopsTimeoutLoop` and `TestServerStartListenerFailureStopsTimeoutLoop` after implementation.
