<!-- task=m-node-multi-target-serving-foundation/07+02_runtime_concurrency plan=1 tag=REVIEW_REFACTOR -->

# Plan - REVIEW_REFACTOR

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

이 계획은 `code_review_cloud_G08_0.log`의 FAIL Required 이슈를 해결하는 후속 작업이다. 구현 중 사용자에게 직접 질문하지 말고, 사용자 전용 blocker는 `CODE_REVIEW-cloud-G08.md`의 `사용자 리뷰 요청`에 근거와 재개 조건을 기록한 뒤 중단한다.

## 배경

이전 구현은 global `runtime.concurrency` 기반 reject gate를 추가했지만, 제한 초과가 실제 Edge-Node transport 경계에서 관측 가능한 이벤트/상태로 전달되지 않고, adapter `Capabilities.MaxConcurrency`도 실행 gate에 반영되지 않았다. 또한 node run path와 bootstrap wiring 변경에 필요한 repo edge-node 진단/full-cycle 검증 증거가 없다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/inference-provider-extension/milestones/node-multi-target-serving-foundation.md`
- Task ids:
  - `runtime-concurrency`: `runtime.concurrency`와 adapter capability가 Node 멀티 호출에서 실제 제한 또는 스케줄링 정책으로 적용된다.
- Completion mode: check-on-pass

## 구현 체크리스트

- [ ] 제한 초과 reject가 Edge-Node transport 경계에서 관측 가능한 error `RunEvent` 또는 동등 계약으로 전달되고 store terminal 상태가 테스트로 고정된다.
- [ ] global runtime limit과 adapter/profile `MaxConcurrency`의 effective limit 계산/우선순위가 구현되고 조합 테스트가 추가된다.
- [ ] node run path/bootstrap 변경에 필요한 Go tests와 repo edge-node diagnostic/full-cycle 검증 또는 명확한 차단 사유가 review stub에 기록된다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REFACTOR-1] Reject Contract

- 문제: `OnRunRequest`가 concurrency 초과를 error return으로만 처리하면 `transport.Session` listener는 이를 로그로만 남긴다. Edge는 rejected run을 이벤트나 store 상태로 관측할 수 없다.
- 해결 방법: reject-on-exceed 정책을 유지하되, 제한 초과 시 session으로 `RunEvent{type:error}` 같은 명확한 실행 이벤트를 전송하거나 동등한 transport 계약을 구현한다. store에는 `failed` 또는 `rejected`처럼 재조회 가능한 terminal 상태와 error message를 남긴다. 구현이 store record를 만들지 않는 정책을 선택한다면 그 이유와 Edge 관측 계약을 테스트로 고정한다.
- 수정 파일 후보:
  - `apps/node/internal/node/node.go`
  - `apps/node/internal/node/node_test.go`
  - 필요 시 `apps/node/internal/transport/integration_test.go`
- 테스트 결정: 추가한다. 제한 초과 run이 adapter를 실행하지 않고, Edge 관측 이벤트/응답과 store 상태가 모두 기대값인지 검증한다.
- 중간 검증:
  - `go test -race -count=1 ./apps/node/internal/node/...`

### [REVIEW_REFACTOR-2] Effective Concurrency

- 문제: adapter `Capabilities.MaxConcurrency`가 command 응답에만 남고 runtime scheduling에는 사용되지 않는다. Roadmap Target의 adapter capability 적용 조건을 충족하지 못한다.
- 해결 방법: resolved adapter의 `Capabilities(ctx).MaxConcurrency`와 Node global runtime concurrency의 effective limit 규칙을 구현한다. 예: global > 0과 adapter > 0이 모두 있으면 더 엄격한 값을 적용하고, global <= 0이면 adapter cap을 fallback으로 사용한다. 다른 정책을 선택할 경우 코드 주석, 테스트명, review stub의 설계 결정에 같은 규칙을 일관되게 남긴다.
- 수정 파일 후보:
  - `apps/node/internal/node/node.go`
  - `apps/node/internal/node/run_manager.go`
  - `apps/node/internal/node/node_test.go`
- 테스트 결정: 추가한다. global unset + adapter cap, global cap + adapter cap, background run 조합을 포함한다.
- 중간 검증:
  - `go test -race -count=1 ./apps/node/internal/node/...`

### [REVIEW_REFACTOR-3] Verification Evidence

- 문제: node run path와 bootstrap wiring을 바꾼 작업인데 Go package tests만 기록되었다. node/testing domain은 repo 내부 edge-node 진단과 변경 범위에 맞는 full-cycle 실제 구동 증거를 요구한다.
- 해결 방법: 코드 수정 후 `agent-ops/skills/project/e2e-smoke/SKILL.md` 기준으로 repo 내부 edge-node diagnostic을 수행한다. 보조 smoke(`./scripts/e2e-smoke.sh` 또는 `make test-e2e`)를 실행했다면 full-cycle 증거와 분리해서 기록한다. 환경상 불가능하면 시도한 명령, 실제 출력, 불가능한 이유, 남은 위험을 `CODE_REVIEW-cloud-G08.md`에 남긴다.
- 테스트 결정: 검증 증거를 수집한다.
- 최종 검증:
  - `go test -race -count=1 ./apps/node/internal/node/...`
  - `go test -count=1 ./apps/node/...`
  - repo 내부 edge-node diagnostic/full-cycle: `agent-ops/skills/project/e2e-smoke/SKILL.md`의 `bin-diagnostic` 또는 변경 범위에 맞는 절차
  - 보조 smoke 가능 시: `./scripts/e2e-smoke.sh`

## 리뷰어를 위한 체크포인트

- 제한 초과 run이 Edge에서 관측 가능한 실패로 남고, silent log-only failure가 아니다.
- `MaxConcurrency`가 command display 값이 아니라 actual scheduling/effective limit에 반영된다.
- foreground/background 모두 같은 effective limit path를 탄다.
- full-cycle/diagnostic evidence와 보조 smoke evidence가 서로 대체되지 않고 구분되어 있다.
