<!-- task=m-runtime-reconnect-config-refresh/04+02_config_push_contract plan=2 tag=REVIEW_REVIEW_NCPUSH -->

# Plan - REVIEW_REVIEW_NCPUSH

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

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증을 실행하고, 실제 구현 내용과 실제 stdout/stderr를 리뷰 stub에 채운 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 최종 archive, `complete.log`, roadmap 완료 처리는 code-review/runtime 책임이다. 선택된 Milestone의 `구현 잠금 > 결정 필요` 항목 때문에 구현이 막힐 때만 리뷰 stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 적고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하거나, `USER_REVIEW.md`/`complete.log`를 직접 만들지 않는다. 환경/secret/service 차단, 일반 범위 조정, 후속 에이전트가 닫을 수 있는 evidence 공백은 사용자 리뷰 요청이 아니다.

## 배경

이 follow-up은 `REVIEW_NCPUSH` 리뷰에서 발견된 검증 공백만 보완한다. Edge는 `NodeConfigRefreshRequest`에 `request_id`와 node별 `NodeConfigPayload`를 넣도록 구현되었고 대상 패키지 테스트도 통과했다. 하지만 fake node runtime test는 payload가 non-nil/non-empty인지까지만 확인해서, 계획이 요구한 "updated payload 내용"과 SDD S12의 refresh payload push evidence를 충분히 증명하지 못한다.

## 사용자 리뷰 요청 흐름

구현 중 사용자 리뷰 요청은 선택된 Milestone lock decision이 실제 구현을 막을 때만 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 해당 섹션은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 템플릿을 따른다. 구현 에이전트는 직접 사용자에게 질문하지 않으며, code-review가 요청 타당성을 검증하고 필요할 때만 `USER_REVIEW.md`를 작성한다.

## Archive Evidence Snapshot

- Current archived plan: `agent-task/m-runtime-reconnect-config-refresh/04+02_config_push_contract/plan_cloud_G07_1.log`
- Current archived review: `agent-task/m-runtime-reconnect-config-refresh/04+02_config_push_contract/code_review_cloud_G07_1.log`
- Verdict: FAIL
- Required summary:
  - `apps/edge/internal/bootstrap/runtime_test.go:1004` says the payload should contain updated provider capacity, but the test only asserts a non-nil payload with at least one adapter.
  - The runtime test changes `nodes[].providers[].capacity`, while `NodeConfigPayload` currently carries adapter/runtime config, not `NodeRecord.Providers`, so the test does not prove refreshed node-specific payload contents.
- Affected files: `apps/edge/internal/bootstrap/runtime_test.go`; optionally `apps/edge/internal/transport/server_test.go` if a more focused `PushConfigRefresh` payload-capture test is clearer.
- Verification evidence from failed loop: `go test -count=1 ./apps/edge/internal/transport ./apps/edge/internal/bootstrap ./apps/node/internal/transport ./apps/node/internal/node` passed, and `make proto && go test -count=1 ./packages/go/... ./proto/gen/...` passed, but payload-content evidence remains incomplete.
- Narrow reread allowed: the two current archived log files listed above.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/update-plane-self-update-foundation/milestones/runtime-reconnect-config-refresh.md`
- Task ids:
  - `push-contract`: Edge-to-Node config refresh message 또는 command 계약이 proto/config 구조에 추가되고 backward compatibility 기준이 정리된다. 검증: generated proto와 handler 테스트가 통과한다.
- Completion mode: check-on-pass

## 범위 결정 근거

- 포함: captured `NodeConfigRefreshRequest.Config`의 구체 payload assertion, misleading capacity comment 정리, request id / changed paths / node result 기존 assertion 유지.
- 제외: `NodeConfigPayload` schema 확장, provider catalog를 payload에 싣는 설계 변경, Node adapter diff/live apply, drain/runtime-config 구현. 이들은 후속 `adapter-diff`, `drain`, `runtime-config` 범위다.
- lane/GNN: `cloud-G07`. 작업은 작지만 SDD S12 evidence trust와 Edge/Node proto transport 계약 검증을 닫는 리뷰 루프다.

## 구현 체크리스트

- [ ] `TestRefreshConfigApplyIncludesNodeResults` 또는 별도 `PushConfigRefresh` 테스트가 captured `NodeConfigRefreshRequest.Config`의 구체 필드를 expected refreshed `NodeStore` record와 대조한다. 최소한 typed adapter config의 type/name/provider/endpoint/capacity 또는 runtime workspace/concurrency처럼 `NodeConfigPayload`에 실제 존재하는 필드를 assert한다.
- [ ] 기존 runtime integration test의 `request_id`, `changed_paths`, connected node result, skipped disconnected node result 검증을 유지하고, `nodes[].providers[].capacity`가 `NodeConfigPayload` 필드인 것처럼 보이는 주석/기대 문구를 실제 계약에 맞게 고친다.
- [ ] 회귀 검증으로 `go test -count=1 ./apps/edge/internal/transport ./apps/edge/internal/bootstrap`, `go test -count=1 ./apps/node/internal/transport ./apps/node/internal/node`, `make proto`, `go test -count=1 ./packages/go/... ./proto/gen/...`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- 이 follow-up은 동일 split subtask `04+02_config_push_contract` 안의 FAIL 보완이다.
- 새 archive evidence는 현재 task 디렉터리의 `plan_cloud_G07_1.log`와 `code_review_cloud_G07_1.log`만 좁게 참조한다.
- PASS 전에는 후속 `05+04_node_adapter_diff`와 `06+05_node_drain_runtime_config`를 진행하지 않는다.

### [REVIEW_REVIEW_NCPUSH-1] Payload Content Evidence

#### 문제

`apps/edge/internal/bootstrap/runtime_test.go:1004`는 payload가 updated provider capacity를 담는다고 설명하지만 실제 assertion은 다음 수준에 머문다.

```go
payload := captured.GetConfig()
if payload == nil {
	t.Fatal("expected non-nil NodeConfigPayload in refresh request")
}
if len(payload.GetAdapters()) == 0 {
	t.Errorf("expected at least one adapter in refresh payload, got none")
}
```

이 테스트는 `request_id` 전파와 request 전송은 확인하지만, Edge가 refreshed `NodeStore` record로 node별 payload를 구성한다는 핵심 계약은 증명하지 못한다.

#### 해결 방법

테스트 fixture에 `NodeConfigPayload`로 표현되는 명시적 config를 넣고 captured payload의 구체 필드를 검증한다. 예를 들어 current/candidate config에 명시적 `openai_compat_instances` 또는 CLI profile/runtime 값을 넣고, refresh trigger는 기존처럼 mutable provider capacity 또는 model catalog change로 유지한다. 그런 뒤 fake node가 받은 `captured.GetConfig()`에서 해당 typed adapter/runtime 필드가 기대값과 일치하는지 확인한다.

만약 runtime integration test 하나에 넣으면 의미가 흐려진다면, `apps/edge/internal/transport/server_test.go`에 focused test를 추가해 `Server.SetNodeStore(candidateStore)` 후 connected fake client가 받은 `NodeConfigRefreshRequest.Config`를 직접 검증한다. 어느 방식이든 "non-empty payload"가 아니라 "expected node-specific payload"를 검증해야 한다.

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

- [ ] `apps/edge/internal/bootstrap/runtime_test.go`: captured payload의 concrete typed adapter/runtime field assertion을 추가하고 misleading capacity comment를 수정한다.
- [ ] 선택 사항: `apps/edge/internal/transport/server_test.go`: runtime fixture보다 명확하면 `PushConfigRefresh` payload-capture 단위 테스트를 추가한다.

#### 중간 검증

```bash
go test -count=1 ./apps/edge/internal/transport ./apps/edge/internal/bootstrap
```

## 최종 검증

```bash
go test -count=1 ./apps/edge/internal/transport ./apps/edge/internal/bootstrap
go test -count=1 ./apps/node/internal/transport ./apps/node/internal/node
make proto
go test -count=1 ./packages/go/... ./proto/gen/...
```

기대 결과: targeted Edge/Node tests와 proto/platform-common 검증이 모두 PASS하고, 검증 출력은 `CODE_REVIEW-cloud-G07.md`에 실제 stdout/stderr로 기록된다.
