<!-- task=m-runtime-reconnect-config-refresh/01_reconnect_supervisor plan=2 tag=REVIEW_REVIEW_RECONNECT -->

# PLAN - REVIEW_REVIEW_RECONNECT Follow-up

## 이 파일을 읽는 구현 에이전트에게

이 계획은 `REVIEW_RECONNECT` 리뷰에서 남은 필수 검증 증거 하나만 해결한다. 소스 코드는 이미 대상 Go 테스트와 `iop.db` 산출물 검증을 통과했으므로, 새 코드 변경을 하지 않는다. 단, 진단 중 실제 코드 결함이 새로 드러나면 그 결함과 증거를 `계획 대비 변경 사항`에 기록하고 최소 수정만 수행한다.

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 검증 출력으로 채우는 것이 구현의 마지막 단계다. 검증을 실행하고 실제 stdout/stderr를 붙인 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review 스킬 전용이다.

선택된 Milestone의 `구현 잠금 > 결정 필요` 항목이 구현을 차단할 때만 review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 남긴다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 검증 증거 공백, 환경/TTY 문제, 반복 실패는 사용자 리뷰 요청이 아니라 `검증 결과`, `계획 대비 변경 사항`, 또는 일반 follow-up으로 남긴다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/update-plane-self-update-foundation/milestones/runtime-reconnect-config-refresh.md`
- Task ids:
  - `retry-policy`: Node reconnect 기본값이 `interval=10s`, `max_attempts=10`으로 고정되고 config/문서/로그에 노출된다.
  - `supervisor`: Node bootstrap lifecycle이 최초 connect 성공 이후 Edge disconnect를 감지하고 reconnect supervisor로 세션을 재수립한다.
  - `exit-limit`: 재접속 실패가 retry 한계를 넘으면 Node가 adapter/store/session을 정리하고 process 종료 신호를 반환한다.
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Current archived plan: `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/plan_cloud_G07_1.log`
- Current archived review: `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/code_review_cloud_G07_1.log`
- Verdict: FAIL
- Required summary:
  - `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/code_review_cloud_G07_1.log:197` shows the second repo internal edge-node diagnostic run ended with `concurrency_unavailable` instead of a second `start` -> non-empty `message` -> `complete` relay.
  - `agent-ops/rules/project/domain/testing/rules.md` and `agent-test/local/node-smoke.md` require two same-session messages to complete on the edge console and require run-by-run node local `[node-message]` payloads to match edge rendered `[node-*-message]` payloads in content/order.
  - Reviewer reran `go test -count=1 ./packages/go/config ./apps/node/cmd/node ./apps/node/internal/transport ./apps/node/internal/bootstrap ./apps/edge/internal/transport`, `git status --short apps/node/internal/bootstrap/iop.db`, `git diff --check`, and `./scripts/e2e-smoke.sh`; all passed, but `./scripts/e2e-smoke.sh` explicitly remains auxiliary and does not replace `scripts/dev/edge.sh` + `scripts/dev/node.sh` evidence.
- Affected files expected:
  - `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/CODE_REVIEW-cloud-G07.md`
- Roadmap carryover: keep the same Roadmap Targets. Do not include `dedupe` in PASS completion metadata.
- Archive files allowed for exact prior context: `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/plan_cloud_G07_1.log` and `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/code_review_cloud_G07_1.log` only.

## 범위 결정 근거

- 포함: repo 내부 edge-node 진단 증거 재수집, active review 파일의 검증 결과 기록.
- 제외: Node reconnect supervisor 코드, config/default, tests, roadmap, SDD, docs, agent-ops rule 변경.
- 허용: 기본 `configs/*.yaml`로 검증이 불가능한 외부 CLI 상태가 확인되면, tracked config를 오염시키지 않는 임시 config와 `IOP_EDGE_CONFIG`/`IOP_NODE_CONFIG`를 사용해도 된다. 이 경우에도 반드시 `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 실행한 출력이어야 하며, `./scripts/e2e-smoke.sh` 출력만 복사해서는 안 된다.

## 구현 체크리스트

- [ ] `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 별도 프로세스로 실행하고 edge console에서 `/nodes`, `/capabilities`, `/transport`, `/sessions` 응답을 기록한다.
- [ ] 같은 session에서 메시지 2회를 보내되, 두 번째 메시지는 첫 번째 run의 `[node*-evt] complete`가 edge console에 표시된 뒤에만 보낸다.
- [ ] 두 run 각각에 대해 edge console의 `[edge] sent`, `[node*-evt] start`, 비어 있지 않은 `[node*-msg]`, `[node*-evt] complete` 순서와 run id를 기록한다.
- [ ] node local 출력의 `[node-message]` payload와 edge rendered `[node*-msg]` payload가 run별로 내용/순서까지 일치한다는 비교 근거를 기록한다.
- [ ] 보조 smoke와 대상 Go 테스트를 fresh rerun하고, `git status --short apps/node/internal/bootstrap/iop.db`가 비어 있음을 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_RECONNECT-1] Repo Internal Edge-Node User-Flow Evidence

#### 문제

이전 follow-up은 `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 실행했지만 두 번째 메시지를 첫 번째 run 완료 전에 보내서 `concurrency_unavailable`로 거부되었다. testing domain 기준의 "메시지 2회 왕복"은 두 요청이 각각 정상 run으로 `start`/`message`/`complete`까지 도달해야 한다.

#### 해결 방법

- edge console 입력을 수동 PTY, code-server, 원격 runner, 또는 FIFO로 제어한다.
- 첫 번째 prompt 전송 후 edge console에 해당 run의 complete event가 보일 때까지 기다린다.
- complete 이후 두 번째 prompt를 보낸다.
- 두 prompt는 서로 구분 가능한 짧은 응답을 요구한다.
- `/nodes`, `/capabilities`, `/transport`, `/sessions`는 실제 edge console 출력과 node command 응답을 그대로 기록한다.
- node local output과 edge output을 나란히 비교하고, echo인 `[edge-message]`가 아니라 node-generated payload와 edge-rendered payload를 기준으로 일치 여부를 적는다.

#### 수정 파일 및 체크리스트

- [ ] `agent-task/m-runtime-reconnect-config-refresh/01_reconnect_supervisor/CODE_REVIEW-cloud-G07.md`: 실제 진단 출력과 비교 근거 기록

#### 테스트 작성

- 테스트 코드 추가는 불필요하다.

#### 중간 검증

```bash
scripts/dev/edge.sh
scripts/dev/node.sh
```

기대 결과: 같은 session 메시지 2회가 각각 edge 화면에서 `start` -> non-empty `message` -> `complete` 순서로 끝나고, node local payload와 edge rendered payload가 run별로 일치한다.

## 최종 검증

```bash
go test -count=1 ./packages/go/config ./apps/node/cmd/node ./apps/node/internal/transport ./apps/node/internal/bootstrap ./apps/edge/internal/transport
```

Expected: targeted config, node CLI config print, node transport, bootstrap reconnect lifecycle, and edge transport tests pass.

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

Expected: auxiliary smoke passes and remains clearly separated from required repo internal diagnostic.

```bash
git status --short apps/node/internal/bootstrap/iop.db
```

Expected: no output.

Repo internal edge-node diagnostic remains required: run `scripts/dev/edge.sh` and `scripts/dev/node.sh` in separate processes and record `/nodes`, message x2, node-local/edge-rendered payload matching, `/capabilities`, `/transport`, and `/sessions`.
