# Code Review Reference - API ## 개요 date=2026-05-04 task=edge_multi_point_routing, plan=0, tag=API ## 이 파일을 읽는 리뷰 에이전트에게 각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요. 리뷰 완료 후 반드시 아래 순서로 아카이브하세요. 1. `CODE_REVIEW.md` → `code_review_N.log` (N = 기존 code_review_*.log 수) 2. `PLAN.md` → `plan_M.log` (M = 기존 plan_*.log 수) 3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 `PLAN.md` + `CODE_REVIEW.md` 스텁 작성. --- ## 구현 항목별 완료 여부 | 항목 | 완료 여부 | |------|---------| | [API-1] Registry를 임의 Pick에서 명시적 조회 API 중심으로 전환 | [x] | | [API-2] Console 실행/세션 종료를 target node 명시 모델로 변경 | [x] | | [API-3] RunEvent에 node 출처를 추가해 foreground/background 출력 모두 node-aware 하게 만들기 | [x] | ## 계획 대비 변경 사항 - `apps/node/internal/node/node.go`의 `sessionSink`를 테스트하기 위해 `protoSender` 인터페이스를 도입했습니다. 이를 통해 `toki` 의존성 없이 `iop.RunEvent` 필드(특히 `node_id`)가 올바르게 채워지는지 단위 테스트할 수 있게 되었습니다. ## 주요 설계 결정 - **Implicit Resolve Logic**: `Resolve("")` 호출 시 연결된 node가 정확히 1개인 경우에만 성공하도록 하여, 하위 호환성을 유지하면서도 멀티 노드 환경에서의 모호성을 원천 차단했습니다. - **Unified Node Labeling**: `consoleEventRouter.nodeLabel` helper를 통해 `node_id`를 `alias`로 변환하는 로직을 일원화하고, registry에 없는 노드라도 `node_id`를 그대로 출력하여 추적성을 보장했습니다. - **State Consolidation**: Console의 상태를 `consoleTarget` 구조체로 묶어 관리함으로써, `/node`, `/session`, `/background` 등 여러 명령이 상태를 안전하게 변경하고 전파할 수 있게 했습니다. ## 리뷰어를 위한 체크포인트 - `apps/edge/internal/node/registry.go: Resolve`가 빈 ref에서 단일 node만 자동 선택하고, multi-node에서는 반드시 명시적 선택 에러를 반환하는지 확인 - `apps/edge/cmd/edge/console.go` 내의 `sendConsoleRun`, `sendTerminateSession`, `sendConsoleStatus`가 모두 `resolveConsoleNode`를 거쳐 `Registry.Pick()` 직접 호출을 제거했는지 확인 - `RunEvent.node_id`가 `apps/node/internal/node/node.go`에서 실제로 채워지고, `apps/edge/cmd/edge/console_events.go`에서 `[node-{alias|id}-...]` 형식으로 출력되는지 확인 ## 검증 결과 ### API-1 중간 검증 ```bash $ go test ./apps/edge/internal/node/... ./apps/edge/internal/transport/... ok iop/apps/edge/internal/node 0.003s ok iop/apps/edge/internal/transport 0.006s ``` ### API-2 중간 검증 ```bash $ go test ./apps/edge/cmd/edge/... ./apps/edge/internal/node/... ok iop/apps/edge/cmd/edge 0.004s ok iop/apps/edge/internal/node (cached) ``` ### API-3 중간 검증 ```bash $ make proto protoc \ --go_out=. \ --go_opt=module=iop \ --proto_path=. \ proto/iop/runtime.proto \ proto/iop/node.proto \ proto/iop/control.proto \ proto/iop/job.proto $ go test ./apps/node/internal/node/... ./apps/edge/cmd/edge/... ok iop/apps/node/internal/node 0.007s ok iop/apps/edge/cmd/edge (cached) ``` ### 최종 검증 ```bash $ make proto (already up to date) $ go test ./apps/edge/... ./apps/node/internal/node/... ok iop/apps/edge/cmd/edge (cached) ok iop/apps/edge/internal/node (cached) ok iop/apps/edge/internal/transport (cached) ok iop/apps/node/internal/node (cached) $ go test ./... ? iop/apps/control-plane/cmd/control-plane [no test files] ok iop/apps/edge/cmd/edge (cached) ? iop/apps/edge/internal/bootstrap [no test files] ok iop/apps/edge/internal/node (cached) ok iop/apps/edge/internal/transport (cached) ? iop/apps/node/cmd/node [no test files] ok iop/apps/node/internal/adapters (cached) ok iop/apps/node/internal/adapters/cli (cached) ? iop/apps/node/internal/adapters/cli/internal/testutil [no test files] ok iop/apps/node/internal/adapters/cli/lifecycle (cached) ok iop/apps/node/internal/adapters/cli/oneshot (cached) ok iop/apps/node/internal/adapters/cli/persistent (cached) ok iop/apps/node/internal/adapters/cli/status (cached) ? iop/apps/node/internal/adapters/mock [no test files] ? iop/apps/node/internal/adapters/ollama [no test files] ? iop/apps/node/internal/adapters/vllm [no test files] ok iop/apps/node/internal/bootstrap (cached) ok iop/apps/node/internal/node (cached) ok iop/apps/node/internal/router (cached) ? iop/apps/node/internal/runtime [no test files] ok iop/apps/node/internal/store (cached) ok iop/apps/node/internal/transport 0.006s ? iop/apps/worker/cmd/worker [no test files] ? iop/packages/auth [no test files] ok iop/packages/config (cached) ? iop/packages/jobs [no test files] ? iop/packages/metadata [no test files] ? iop/packages/observability [no test files] ? iop/packages/policy [no test files] ? iop/packages/version [no test files] ? iop/proto/gen/iop [no test files] ``` ## 코드리뷰 결과 - 종합 판정: FAIL - 차원별 평가 - correctness: Pass - completeness: Fail - test coverage: Fail - API contract: Pass - code quality: Pass - plan deviation: Fail - verification trust: Pass - 발견된 문제 - Required — [apps/edge/cmd/edge/console.go](/config/workspace/go-iop/apps/edge/cmd/edge/console.go:126): `/terminate-session` 성공 메시지가 여전히 `terminated session `만 출력해, 계획서의 "startup banner와 `/terminate-session` 결과도 `node=`를 포함" 요구를 충족하지 못합니다. 멀티 노드 환경에서 어떤 node의 세션을 종료했는지 즉시 확인할 수 없고, 이에 대한 회귀 테스트도 없습니다. 성공 경로에서 `resolveConsoleNode(...)`로 얻은 node label을 포함해 `terminated session node=` 형태로 출력하고, console 테스트에 해당 문자열을 검증하는 케이스를 추가하세요. - 다음 단계 - FAIL: Required 이슈를 반영하는 새 `PLAN.md`와 `CODE_REVIEW.md` 스텁을 작성하고 리뷰 루프를 계속한다.