<!-- task=m-provider-resource-admission-ownership-alignment/11+08,13,15_reconnect_candidate_recovery plan=1 tag=REVIEW_REFACTOR -->

# Reconnect dispatch-ready handoff and terminal convergence

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

Implementation 모델은 Plan/Review 모델과 달라야 한다. 이 계획의 코드·테스트·계약 변경과 검증을 수행하고 review stub의 구현 에이전트 소유 섹션을 모두 채운 뒤 `review-ready`를 보고하고 종료한다. code-review를 실행하거나 다음 에이전트를 시작하지 않는다.

## 역할 모델

- Plan: `root-followup-plan`
- Implementation/Review identity 원장은 `CODE_REVIEW-cloud-G10.md`에 있으며 Runtime이 각 역할 시작 시 기록한다.

## 배경

이전 구현은 accepted registration 직후 `RegisterResponse`가 Node에 도착하기 전에 reconnect waiter를 pump한다. Node는 response의 config로 adapter를 만들고 session handler를 설치한 뒤에야 실행 가능하므로, 이 순서에서는 첫 `RunRequest`/`ProviderTunnelRequest`가 유실되고 Edge lease가 terminal을 기다리며 남을 수 있다. SDD S15를 유지하되 Node가 config 적용과 handler 설치를 완료했다는 명시적 ready handoff 뒤에만 dispatch eligibility와 queue pump를 열어야 한다.

## 사용자 리뷰 요청 흐름

선택 Milestone의 `구현 잠금 > 결정 필요`만 active review stub의 `사용자 리뷰 요청`에 기록한다. 구현 중 직접 user prompt는 금지되며 code-review가 요청 검증과 실제 `USER_REVIEW.md` 작성을 소유한다. 환경·endpoint·secret·live provider blocker는 검증 evidence와 해제 조건으로 남기고 user review로 바꾸지 않는다.

## Archive Evidence Snapshot

- 이전 task: `agent-task/m-provider-resource-admission-ownership-alignment/11+08,13,15_reconnect_candidate_recovery`
- 이전 plan/review: `plan_cloud_G08_0.log`, `code_review_cloud_G08_0.log`; verdict=`FAIL`.
- Required 1: `apps/edge/internal/transport/connection_handlers.go:121`의 connect hook이 `RegisterResponse` 반환보다 먼저 queue를 pump하지만 Node handler는 `apps/node/internal/bootstrap/module.go:102-108`에서 나중에 설치된다.
- Required 2: transport hook/service queue 단위 테스트는 통과했으나 실제 Node reconnect, 기존 waiter dispatch, terminal exactly-once, lease/counter 0 수렴을 한 흐름에서 검증하지 않는다.
- Required 3: mock smoke는 보조 검증이며 `scripts/dev/edge.sh` + `scripts/dev/node.sh` 실제 user-flow가 없었다. `scripts/e2e-long-context-admission-smoke.sh --preflight`는 provider/status endpoint 미도달로 rc=3이었다.
- 보존된 유효 evidence: generation fence, reconnect candidate rebuild, event-before-correctness 분리는 대상/전체 Go test와 race에서 통과했다. legacy role marker 부재는 사용자 명시 예외이므로 차단 사유가 아니다.
- 세부 문맥이 필요할 때만 위 두 log와 `NEXT_STATE.md`를 다시 읽는다. 다른 archive를 탐색하지 않는다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/provider-resource-admission-ownership-alignment.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/provider-resource-admission-ownership-alignment.md)
- Task ids:
  - `reconnect-candidate-recovery`: accepted reconnect가 dispatch-ready generation만 후보로 복구하고 기존 waiter를 terminal까지 정확히 한 번 실행
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `AGENTS.md`, `agent-ops/rules/project/rules.md`, `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/project/domain/edge/rules.md`, `node/rules.md`, `platform-common/rules.md`, `testing/rules.md`
- `agent-ops/rules/common/rules-agent-spec.md`, `agent-ops/skills/common/router.md`, `plan/SKILL.md`, `finalize-task-routing/SKILL.md`
- `agent-ops/skills/project/e2e-smoke/SKILL.md`
- `agent-test/local/rules.md`, `edge-smoke.md`, `node-smoke.md`, `platform-common-smoke.md`, `testing-smoke.md`
- `agent-roadmap/current.md`, 선택 Phase/Milestone 문서, 승인된 SDD.
- `agent-contract/index.md`, `agent-contract/inner/edge-node-runtime-wire.md`
- `agent-spec/index.md`, `agent-spec/runtime/edge-node-execution.md`, `agent-spec/runtime/provider-pool-config-refresh.md`
- `proto/iop/runtime.proto:1-180,205-330`, `Makefile:97-132`.
- `apps/edge/internal/node/registry.go:15-201`, `registry_test.go`의 generation/resolve/lifecycle 범위.
- `apps/edge/internal/transport/server.go:30-229`, `connection_handlers.go:1-190`, `integration_test.go:1000-1133`.
- `apps/edge/internal/bootstrap/runtime.go:24-188`, `runtime_refresh_node_test.go:24-190,558-710`, `runtime_test_support_test.go:1-191`.
- `apps/edge/internal/service/service.go:45-120,200-245`, `provider_resolution.go:260-470`, `model_queue_admission.go:300-480`, `model_queue_types.go:380-490`, `model_queue_release.go:140-250`, `run_submit.go:1-190`, `run_types.go:1-114`, `status_provider.go:100-190`.
- `apps/edge/internal/service/service_internal_test.go:1518-1685`, `queue_dispatch_test.go:1140-1365`, `status_provider_test.go:2180-2302`.
- `apps/node/internal/transport/client.go:95-200`, `session.go:1-220`, `parser.go:1-40`, `client_test.go`의 registration 범위.
- `apps/node/internal/bootstrap/module.go:60-115`, `runtime_supervisor.go:1-214`, `module_test.go:1-260,420-680`.
- `scripts/dev/edge.sh`, `scripts/dev/node.sh`, `scripts/e2e-smoke.sh:1-620`, `scripts/e2e-long-context-admission-smoke.sh:1-520`.
- 이전 `NEXT_STATE.md`, `plan_cloud_G08_0.log`, `code_review_cloud_G08_0.log`.
- predecessor `08_disconnect_exclusion`, `13+09_disconnect_queue_settlement`, `15+14_controlplane_connected_mapping`의 `complete.log`.

### SDD 기준

- SDD: `agent-roadmap/sdd/operational-observability-provider-management/provider-resource-admission-ownership-alignment/SDD.md`; 상태 `[승인됨]`, 잠금 `해제`, USER_REVIEW 없음.
- S15 → `reconnect-candidate-recovery`: reconnect만으로 기존 waiter를 live candidate에 dispatch하되 stale/rejected connection은 wake-up하지 않는다.
- S02/S09 보조 불변식: 실제 terminal은 lease를 정확히 한 번 반환하고 최종 normal/long in-flight와 queue가 0으로 수렴한다.
- Evidence Map의 deterministic connectivity/queue test와 race를 ready-ordering test, 실제 Node subprocess 통합 회귀, 대상 race/전체 회귀로 구체화한다. `Roadmap Targets`는 S15를 닫는 이 closure task에 유지한다.

### 테스트 환경 규칙

- `test_env=local`; 위 local rule과 edge/node/platform-common/testing smoke profile을 사용한다.
- proto 원본 변경은 `make proto`로 Go 생성물을 갱신하고 생성 파일을 직접 편집하지 않는다. Client는 Edge-Node wire 소비자가 아니므로 `make proto-dart`는 생략하되 사유를 review stub에 기록한다.
- Go cache의 stale 성공을 피하려고 모든 correctness 명령에 `-count=1` 이상을 사용한다. 반복 회귀는 명시된 count를 그대로 실행한다.
- `scripts/dev` 검증은 두 별도 프로세스와 edge console 입력을 사용한다. mock E2E는 보조로만 기록한다.
- live provider는 `--preflight`가 config, `/models`, Control Plane status, provider identity/health/capacity를 증명해야 한다. rc=3이면 exact blocker와 `/tmp` evidence 경로를 기록하고, endpoint/identity가 준비된 뒤 같은 명령을 재실행한다.

### 테스트 커버리지 공백

- 기존 transport test는 registration 직후 hook/event 순서만 보며 RegisterResponse/config/handler-ready 경계를 표현하지 않는다.
- 기존 service tests는 `HandleNodeConnect`를 직접 호출해 실제 Node가 request listener를 설치했는지 검증하지 않는다.
- 기존 Node bootstrap tests는 reconnect registration을 검증하지만 ready ack 이전에 Edge가 실행 요청을 보내지 않는다는 계약을 검증하지 않는다.
- 기존 reconnect test의 terminal은 service method를 직접 호출하므로 실제 Node terminal event와 Edge exactly-once release가 한 흐름에 없다.
- 실제 `scripts/dev` user-flow와 live provider preflight 재검증 evidence가 없다.

### 심볼 참조

- 변경/추가 후보: `RegisterRequest`/`RegisterResponse` 인접 ready message, `Server.notifyNodeConnected`, `Service.HandleNodeConnect`, `Registry.Resolve`/`All` 기반 dispatch 조회, `Session.SetHandler`, `connectRuntime`.
- `Registry.All()` 직접 소비: `provider_resolution.go`, `service.go`, `status_provider.go`; refresh push는 `Server.PushConfigRefresh`의 `Registry.Get`를 사용한다. dispatch/connected snapshot/refresh가 pending accepted entry를 ready로 오인하지 않게 전부 분류한다.
- `Registry.Resolve()` 소비: service direct dispatch와 ops console alias enrichment. dispatch 경로는 ready-only resolve를 사용하고 관측용 조회와 구분한다.
- 제거 심볼은 없다. 기존 `notifyNodeConnected` 호출 위치는 registration response 전에서 ready request accept 후로 이동한다.

### 분할 판단

- 선택 candidate는 기존 task path의 FAIL follow-up 하나다. ready wire, registry eligibility, Node handler 설치, waiter terminal 회귀가 같은 handshake/state transition을 공유하므로 단일 task로 유지한다.
- complete immediate sibling set: `11+08,13,15_reconnect_candidate_recovery` 하나. write set은 proto/generated wire, Edge registry/transport/service/bootstrap tests, Node transport/bootstrap tests, 계약/spec이다.
- shared mutable state는 registry owner generation, dispatch-ready bit, queue resource/lease다. 분리 시 동일 파일과 상태를 중복 수정하므로 collision이 있으며 병렬 split하지 않는다.
- predecessor 08/13/15는 각각 `agent-task/archive/2026/07/m-provider-resource-admission-ownership-alignment/08_disconnect_exclusion/complete.log`, `13+09_disconnect_queue_settlement/complete.log`, `15+14_controlplane_connected_mapping/complete.log`로 충족됐다.

### 범위 결정 근거

- ready는 별도 wire request/ack로 표현하고 internal `connection_generation`은 SDD대로 wire/config field로 노출하지 않는다.
- pending accepted connection은 duplicate ownership claim에는 참여하지만 direct/provider-pool dispatch, refresh push, connected snapshot/event에는 ready 전 참여하지 않는다.
- disconnect generation fence, lease release 알고리즘, provider policy/config schema, retry 횟수 정책은 유효한 predecessor 구현이므로 변경하지 않는다.
- user-flow 검증을 위해 `scripts/dev/*`를 공식 field UX로 승격하거나 기본 `configs/*.yaml`을 임시값으로 수정하지 않는다.
- live provider endpoint/secret/inventory를 tracked 문서에 기록하지 않는다. script 자체의 기존 scenario/baseline 개편은 이 follow-up 범위가 아니다.

### 최종 라우팅

- `evaluation_mode=isolated-reassessment`; 이전 lane/G/score/filename은 입력과 하한에서 제외했다.
- build closures: `scope_closed=true`(ready handoff·실제 reconnect terminal·검증 조건 고정), `context_closed=false`(proto, Edge registry/queue, Node bootstrap, process integration을 함께 유지), `verification_closed=true`(target/race/full-cycle/live preflight 명령과 기대 결과 고정), `evidence_trusted=true`(FAIL line evidence와 재현 가능한 test entrypoint), `ownership_closed=true`(지정 task의 단일 충돌 write set), `decision_closed=true`(wire-ready ack와 blocker 처리 기준이 승인 SDD/규칙으로 결정됨). cloud가 넓은 cross-domain context를 유지해 context closure를 해소한다. scores=`2,2,2,1,2`; formatter 결과 `cloud/G09`, `PLAN-cloud-G09.md`.
- review closures: `scope_closed=true`, `context_closed=false`(wire ordering, actual Node process, queue/terminal counters, user-flow/live evidence를 함께 대조), `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`. cloud가 전체 evidence 대조 context를 유지한다. scores=`2,2,2,2,2`; formatter 결과 `cloud/G10`, `CODE_REVIEW-cloud-G10.md`.

## 구현 체크리스트

- [ ] RegisterResponse/config 적용과 Node handler 설치가 끝난 뒤 Node가 보내는 명시적 ready request/ack를 추가하고, ready 전 accepted connection을 모든 실행 dispatch·refresh push·connected snapshot/event에서 제외한다.
- [ ] ready accept가 current client/generation에서 정확히 한 번 `HandleNodeConnect`와 global pump를 실행하고 duplicate/stale/rejected ready는 no-op/reject가 되도록 registry·transport·service ordering 회귀를 추가한다.
- [ ] 실제 `iop-node` bootstrap/reconnect와 이미 queue된 waiter를 한 integration test에서 구동해 RunRequest 수신·terminal 1회·중복 dispatch 0회·provider lease/normal/long/queued counter 0 수렴을 검증한다.
- [ ] Edge-Node wire 계약과 living spec의 registration 흐름을 response → config/handler → ready ack → dispatch 가능 순서로 동기화한다.
- [ ] 대상/반복/race/전체 Go 회귀, 직접 `scripts/dev/edge.sh` + `scripts/dev/node.sh` user-flow, 보조 mock smoke, live provider preflight와 해제 후 scenario 재검증 evidence를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채우고 review-ready를 보고한 뒤 현재 실행을 종료한다. code-review를 실행하거나 다음 에이전트를 시작하지 않는다.

### [REVIEW_REFACTOR-1] Explicit Node dispatch-ready handshake

문제: `apps/edge/internal/transport/connection_handlers.go:115-129`는 accepted entry를 등록한 뒤 response를 반환하기 전에 connect hook/pump를 실행한다. 반면 `apps/node/internal/transport/client.go:137-159`는 response 뒤 session을 만들고 `apps/node/internal/bootstrap/module.go:78-108`은 config build, adapter start, Node 생성 후 handler를 설치한다. `apps/node/internal/transport/session.go:41-90`은 handler가 nil이면 run/tunnel request를 버린다.

해결 방법:

```go
// Before: connection_handlers.go:121-129
s.notifyNodeConnected(rec.ID, entry.ConnectionGeneration)
s.emitNodeRegistered(rec)
return &iop.RegisterResponse{Accepted: true, Config: cfg}, nil

// After: registration은 config를 반환하고 pending owner claim만 만든다.
// Node가 config 적용 + handler 설치 뒤 NodeReadyRequest를 보내면,
// current client를 compare-and-ready한 최초 1회만 lifecycle → event → ack 순으로 연다.
```

- proto에는 request/ack identity만 추가하고 generation은 Edge registry 내부 값으로 유지한다.
- Registry는 pending accepted와 dispatch-ready를 구분한다. ready-only resolve/list/current-owner check를 service candidate/direct dispatch, refresh push, connected snapshot에 적용한다.
- Node `connectRuntime`은 `SetHandler` 다음 ready request를 보내고 positive ack를 받아야 owner를 반환한다. send/ack 실패는 session을 닫아 supervisor의 retryable reconnect로 수렴한다.
- ready handler는 current client에 대해 idempotent하다. 첫 transition만 `HandleNodeConnect`와 `node.connected` event를 만들고 duplicate ready는 추가 pump/event 없이 성공 ack, stale client는 reject한다.

수정 파일 및 체크리스트:

- [ ] `proto/iop/runtime.proto`: `NodeReadyRequest`/`NodeReadyResponse` 내부 handshake 계약 추가.
- [ ] `proto/gen/iop/runtime.pb.go`: `make proto` 생성 결과만 반영.
- [ ] `apps/edge/internal/node/registry.go`, `registry_test.go`: pending/ready owner와 current-client idempotent transition, ready-only dispatch lookup.
- [ ] `apps/edge/internal/transport/server.go`, `connection_handlers.go`, `integration_test.go`: ready listener/parser, registration/ready/event ordering, duplicate/stale ready.
- [ ] `apps/edge/internal/service/provider_resolution.go`, `service.go`, `status_provider.go`와 직접 영향 테스트: ready 전 candidate/direct dispatch/snapshot 차단과 pre-send ready fence.
- [ ] `apps/edge/internal/transport/server.go`의 refresh push: ready 전 client에는 config refresh를 보내지 않는다.
- [ ] `apps/node/internal/transport/parser.go`, `session.go`, `client.go`, 대응 transport tests: ready response decode와 bounded request/ack API.
- [ ] `apps/node/internal/bootstrap/module.go`, `module_test.go`: handler 설치 후 ready ack, failure cleanup/retry.
- [ ] `apps/edge/internal/bootstrap/runtime.go` 및 wiring test: ready lifecycle handler 연결이 보존됨을 검증.

테스트 작성: `TestRegistrationDoesNotDispatchBeforeReady`, `TestReadyCurrentOwnerActivatesOnceBeforeConnectedEvent`, `TestSessionReadyRunsAfterHandlerInstallation` 계열로 response 전/후와 stale/duplicate 경계를 직접 단언한다. exact 이름은 기존 test naming과 충돌하지 않게 정하되 review stub에 최종 이름을 기록한다.

중간 검증: `make proto` 후 ready 관련 Edge/Node transport/bootstrap package tests가 통과한다.

### [REVIEW_REFACTOR-2] Actual Node reconnect waiter terminal regression

문제: `apps/edge/internal/service/queue_dispatch_test.go:1162-1328`은 fake socket과 직접 `HandleNodeConnect`/terminal 호출로 queue·counter를 검증하고, `apps/node/internal/bootstrap/module_test.go:509-597`은 실제 `DialEdge` reconnect만 검증한다. 두 테스트 사이의 실제 handler-ready/dispatch/terminal handoff 공백이 이전 FAIL의 유실 경로다.

해결 방법: `apps/edge/internal/bootstrap`의 새 integration test에서 in-process Edge runtime과 subprocess actual `iop-node`를 사용한다. 두 configured CLI provider 중 alternate capacity 1을 blocking fixture로 점유하고 reconnect 대상 Node를 offline으로 만든 뒤 waiter가 실제 queue에 들어갔음을 snapshot으로 확인한다. 같은 Node process entrypoint를 재시작해 ready ack 뒤 waiter가 reconnect provider로 정확히 한 번 dispatch되는지, Node의 terminal `RunEvent`가 한 번 도착하는지, 반복/late terminal에도 lease와 normal/long/queued counter가 0인지 확인한다.

```go
// Before: queue_dispatch_test.go:1288-1293
reg.Register(reconnectEntry)
svc.HandleNodeConnect("node-recon", reconnectEntry.ConnectionGeneration)

// After: actual node bootstrap subprocess reconnect
// RegisterResponse(config) -> SetHandler -> NodeReadyRequest/ack
// -> Edge ready transition -> waiter dispatch -> actual terminal event
```

수정 파일 및 체크리스트:

- [ ] `apps/edge/internal/bootstrap/reconnect_readiness_integration_test.go` 신규: actual node binary/subprocess lifecycle, temp config/scripts, queued waiter and terminal/counter assertions.
- [ ] `apps/edge/internal/bootstrap/runtime_test_support_test.go`: repo-root/binary/process helper가 다른 bootstrap tests에도 안전하게 재사용될 때만 최소 helper 추가; 아니면 새 test 내부에 한정한다.
- [ ] `apps/edge/internal/service/queue_dispatch_test.go`: fake test는 빠른 service regression으로 보존하고 ready transition API에 맞춰 갱신한다.
- [ ] subprocess stdout/stderr는 `t.TempDir()`에 저장하고 failure 때만 출력한다. test cleanup은 process tree와 Edge runtime을 항상 종료하며 repo 파일/config/store를 오염시키지 않는다.

테스트 작성: 신규 test는 (1) waiter queue 확인, (2) ready 전 dispatch 0, (3) reconnect ready 뒤 selected generation/provider로 dispatch 1, (4) actual terminal event 1, (5) duplicate terminal/ready 후 추가 dispatch 0, (6) snapshot normal/long in-flight/queued 0과 lease count 0을 단언한다. timeout polling은 bounded condition 기반으로 하고 blind sleep을 completion evidence로 쓰지 않는다.

중간 검증: 신규 test를 `-count=10`과 `-race -count=1`로 실행해 유실·중복·leak·race가 없다.

### [REVIEW_REFACTOR-3] Wire contract and living spec sync

문제: `agent-contract/inner/edge-node-runtime-wire.md`와 `agent-spec/runtime/edge-node-execution.md`는 register response 뒤 즉시 실행 가능하다고 읽히며 handler-ready handoff가 없다. `agent-spec`의 registration Mermaid는 registry 등록과 response 순서도 현재 코드와 어긋난다.

해결 방법: active 계약과 spec에 accepted registration은 ownership claim/config 전달이고, dispatch readiness는 Node가 config 적용·adapter start·handler 설치 후 ready request/ack로 확정된다는 순서를 기록한다. ready 전에는 run/tunnel/command/config-refresh dispatch와 connected availability/event가 열리지 않으며 stale/duplicate ready는 lifecycle을 반복하지 않는다고 명시한다.

수정 파일 및 체크리스트:

- [ ] `agent-contract/inner/edge-node-runtime-wire.md`: ready request/ack, ordering, failure/retry, ready-before-dispatch 불변식.
- [ ] `agent-spec/runtime/edge-node-execution.md`: 기능 목록, Node 등록 sequence, 검증/한계, 변경 기록 갱신.
- [ ] `agent-spec/runtime/provider-pool-config-refresh.md`: provider 후보의 connected 의미를 dispatch-ready connection으로 좁히고 refresh push readiness를 짧게 반영한다.

테스트 작성: 문서-only assertion은 추가하지 않는다. proto/consumer tests와 `rg` stale wording 확인을 검증으로 사용한다.

## 의존 관계 및 구현 순서

- task directory `11+08,13,15_...`의 predecessor 08/13/15 complete.log는 모두 위 경로로 충족됐다.
- REVIEW_REFACTOR-1의 wire와 ready gate를 먼저 구현한다. REVIEW_REFACTOR-2가 그 public behavior를 실제 process 흐름으로 검증하고, REVIEW_REFACTOR-3이 최종 구현 명칭/순서에 맞춰 계약/spec을 동기화한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `proto/iop/runtime.proto`, `proto/gen/iop/runtime.pb.go` | REVIEW_REFACTOR-1 |
| `apps/edge/internal/node/registry.go`, `registry_test.go` | REVIEW_REFACTOR-1 |
| `apps/edge/internal/transport/server.go`, `connection_handlers.go`, `integration_test.go` | REVIEW_REFACTOR-1 |
| `apps/edge/internal/service/provider_resolution.go`, `service.go`, `status_provider.go` 및 직접 영향 tests | REVIEW_REFACTOR-1 |
| `apps/node/internal/transport/client.go`, `session.go`, `parser.go` 및 tests | REVIEW_REFACTOR-1 |
| `apps/node/internal/bootstrap/module.go`, `module_test.go` | REVIEW_REFACTOR-1 |
| `apps/edge/internal/bootstrap/runtime.go`, `reconnect_readiness_integration_test.go`, 필요 시 test support | REVIEW_REFACTOR-1, REVIEW_REFACTOR-2 |
| `apps/edge/internal/service/queue_dispatch_test.go` | REVIEW_REFACTOR-2 |
| `agent-contract/inner/edge-node-runtime-wire.md`, `agent-spec/runtime/edge-node-execution.md`, `provider-pool-config-refresh.md` | REVIEW_REFACTOR-3 |

## 최종 검증

- workdir `/config/workspace/iop`: `make proto` → exit 0; `runtime.pb.go`는 proto 원본에서 재생성됨.
- `gofmt -d apps/edge/internal/node/registry.go apps/edge/internal/node/registry_test.go apps/edge/internal/transport/server.go apps/edge/internal/transport/connection_handlers.go apps/edge/internal/transport/integration_test.go apps/edge/internal/service/provider_resolution.go apps/edge/internal/service/service.go apps/edge/internal/service/status_provider.go apps/edge/internal/service/service_internal_test.go apps/edge/internal/service/status_provider_test.go apps/edge/internal/service/queue_dispatch_test.go apps/edge/internal/bootstrap/runtime.go apps/edge/internal/bootstrap/runtime_refresh_node_test.go apps/edge/internal/bootstrap/runtime_test_support_test.go apps/edge/internal/bootstrap/reconnect_readiness_integration_test.go apps/node/internal/transport/parser.go apps/node/internal/transport/parser_test.go apps/node/internal/transport/session.go apps/node/internal/transport/session_test.go apps/node/internal/transport/client.go apps/node/internal/transport/client_test.go apps/node/internal/bootstrap/module.go apps/node/internal/bootstrap/module_test.go` → 출력 없음.
- `git diff --check -- proto/iop/runtime.proto proto/gen/iop/runtime.pb.go apps/edge/internal/node apps/edge/internal/transport apps/edge/internal/bootstrap apps/edge/internal/service apps/node/internal/transport apps/node/internal/bootstrap agent-contract/inner/edge-node-runtime-wire.md agent-spec/runtime/edge-node-execution.md agent-spec/runtime/provider-pool-config-refresh.md` → 출력 없음.
- `rg --sort path -n 'NodeReady(Request|Response)|Mark.*Ready|DispatchReady|HandleNodeConnect|notifyNodeConnected' proto/iop apps/edge apps/node agent-contract/inner/edge-node-runtime-wire.md agent-spec/runtime` → ready producer/consumer와 lifecycle callsite가 계획한 순서에만 존재.
- `go test -count=20 -timeout 180s ./apps/edge/internal/node ./apps/edge/internal/transport ./apps/node/internal/transport ./apps/node/internal/bootstrap -run 'Ready|Register|Reconnect'` → PASS.
- `go test -count=10 -timeout 300s ./apps/edge/internal/bootstrap -run '^TestActualNodeReconnectReadyPumpsQueuedWaiterExactlyOnce$'` → 10/10 PASS, terminal/dispatch 중복과 counter leak 0.
- `go test -race -count=1 -timeout 300s ./apps/edge/internal/bootstrap -run '^TestActualNodeReconnectReadyPumpsQueuedWaiterExactlyOnce$'` → PASS, race warning 0.
- `go test -race -count=1 -timeout 300s ./apps/edge/internal/node ./apps/edge/internal/transport ./apps/edge/internal/bootstrap ./apps/edge/internal/service ./apps/node/internal/transport ./apps/node/internal/bootstrap` → PASS.
- `go test -count=1 -timeout 300s ./apps/edge/... ./apps/node/...` → PASS.
- `go test -count=1 -timeout 600s ./...` → PASS.
- 직접 user-flow, terminal A `/config/workspace/iop`: `./scripts/dev/edge.sh`; terminal B: `./scripts/dev/node.sh`. Edge console에서 `/nodes`, 같은 session message 2회, `/capabilities`, `/transport`, `/sessions`, persistent profile이면 `/terminate-session`을 순서대로 실행한다. 각 run의 `[edge] sent → [node-*-event] start → node/edge 동일 payload message → complete` 순서와 reconnect 뒤 동일 cycle을 실제 transcript로 기록한다. 실행 불가 profile은 command/로그인/endpoint별 blocker와 재개 조건을 기록한다.
- `IOP_E2E_BIND_TIMEOUT=60 IOP_E2E_PROFILE=mock ./scripts/e2e-smoke.sh` → 보조 smoke PASS; 직접 scripts/dev transcript와 구분한다.
- `./scripts/e2e-long-context-admission-smoke.sh --preflight --out-dir /tmp/iop-reconnect-ready-preflight` → rc=0이면 provider identity/health/capacity 확인. rc=3이면 exact failed command, output path, endpoint/identity 해제 조건을 기록하고 성공으로 간주하지 않는다.
- preflight rc=0일 때 `./scripts/e2e-long-context-admission-smoke.sh --preflight --scenario normal-10 --out-dir /tmp/iop-reconnect-ready-normal-10` → 모든 HTTP 요청 성공, peak capacity/queue 관측, 최종 in_flight/queued/long counter 0. 이전 rc=3 blocker 해소 뒤 같은 명령으로 재검증한다.

검증 결과를 review stub에 기록하고 review-ready를 보고한 뒤 현재 실행을 종료한다. code-review를 실행하거나 다음 에이전트를 시작하지 않는다.
