<!-- task=review_followup_alignment/04_explicit_mock_resource_activation plan=1 tag=REVIEW_REVIEW_MOCK -->
# PLAN-local-G06: mock explicit activation follow-up
date=2026-07-06

## 목적
Explicit mock activation 전환에서 남은 두 Required 이슈만 좁게 수정한다. `mock` adapter instance key가 provider id와 충돌하지 않게 만들고, mock을 참조하는 Edge surface route가 explicit `adapters.mock.enabled: true` 없이 `config check`를 통과하지 못하게 한다.

## Archive Evidence Snapshot

- Current archived plan: `agent-task/review_followup_alignment/04_explicit_mock_resource_activation/plan_local_G06_0.log`
- Current archived review: `agent-task/review_followup_alignment/04_explicit_mock_resource_activation/code_review_local_G06_0.log`
- Verdict: FAIL
- Required summary:
  1. `apps/edge/internal/node/mapper.go` appends explicit mock but does not reserve flat adapter key `mock`, so a provider id named `mock` can overwrite the mock adapter instance in the Node registry.
  2. `apps/edge/internal/edgevalidate/validate.go` validates node provider adapter references but does not validate `console.adapter: mock`, top-level `openai.adapter: mock`, `openai.model_routes[].adapter: mock`, or `a2a.adapter: mock` against explicit node mock activation.
- Affected files for follow-up: `apps/edge/internal/node/mapper.go`, `apps/edge/internal/node/mapper_test.go`, `apps/edge/internal/edgevalidate/validate.go`, `apps/edge/internal/edgevalidate/validate_test.go`.
- Verification evidence collected during review:
  - `go test -count=1 ./packages/go/config ./apps/edge/internal/node ./apps/edge/internal/edgevalidate ./apps/edge/internal/transport ./apps/node/internal/adapters`: PASS.
  - `rg --sort path -n 'adapter: mock|mock-echo' scripts configs apps -g '!*.pb.go'`: no `adapter: mock`; intentional `mock-echo` references remained in `apps/node/internal/adapters/mock/mock.go` and `apps/node/internal/router/router_test.go`.
  - `bash scripts/e2e-smoke.sh`: PASS.
  - `bash scripts/e2e-openai-ollama.sh`: PASS.
- Narrow reread allowed if needed: the two archived files listed above.
- Roadmap carryover: none.

## 이 파일을 읽는 구현 에이전트에게
구현 후 `CODE_REVIEW-local-G06.md`의 구현 에이전트 소유 섹션을 실제 변경 내용과 검증 출력으로 채운다. 직접 사용자에게 질문하거나 선택지를 제시하지 않는다. 선택된 Milestone의 `구현 잠금 > 결정 필요` 항목이 실제 구현을 차단할 때만 review stub의 `사용자 리뷰 요청` 섹션에 근거를 기록하고 멈춘다.

## 작업 항목

### REVIEW_REVIEW_MOCK-1. mock adapter key를 flat namespace 충돌 검사에 포함
- 문제:
  - `BuildConfigPayload`는 explicit mock adapter를 `Type: "mock"` 및 empty `Name`으로 추가하므로 Node side instance key가 `mock`이 된다.
  - 같은 node에 provider-first resource `id: mock`이 있으면 mapper가 충돌을 거부하지 않고 payload에 같은 instance key를 두 번 실을 수 있다.
- 해결 방법:
  - `seenFlat` 또는 동등한 flat key 예약 구조를 mock 추가 전에 초기화한다.
  - `rec.Adapters.Mock.Enabled`이면 adapter key `mock`을 예약하고, provider id가 같은 key를 쓰면 명확한 conflict error를 반환한다.
  - 기존 duplicate provider id error와 adapter key conflict error가 구분되도록 메시지를 유지하거나 개선한다.
- 체크리스트:
  - [ ] `apps/edge/internal/node/mapper.go`: explicit mock key `mock`을 flat namespace에 예약한다.
  - [ ] `apps/edge/internal/node/mapper_test.go`: `adapters.mock.enabled: true`와 provider id `mock` 조합이 conflict error를 내는 테스트를 추가한다.
- 중간 검증:
  - [ ] `go test -count=1 ./apps/edge/internal/node`

### REVIEW_REVIEW_MOCK-2. mock surface route의 explicit activation validation 추가
- 문제:
  - 계획은 mock route/console 참조가 explicit mock config 없이 실패해야 한다고 요구했지만, 현재 `ValidateEdgeConfig`는 provider adapter reference만 검사한다.
  - `console.adapter: mock` 또는 OpenAI/A2A mock route가 남아도 node payload에는 mock이 없을 수 있어 runtime dispatch 시점까지 오류가 밀린다.
- 해결 방법:
  - `ValidateEdgeConfig`에서 mock을 참조하는 Edge input/console surface를 검사한다.
  - 대상 surface: `console.adapter`, top-level `openai.adapter`, `openai.model_routes[].adapter`, `a2a.adapter`.
  - surface에 `node`/`NodeRef`가 있으면 해당 node에 `adapters.mock.enabled: true`가 있어야 한다. node ref가 없으면 적어도 하나의 configured node가 explicit mock을 활성화해야 한다.
  - OpenAI/A2A는 해당 surface가 enabled일 때만 검사하고, console은 configured adapter가 `mock`일 때 검사한다.
  - node id와 alias 모두 node ref로 해석한다.
- 체크리스트:
  - [ ] `apps/edge/internal/edgevalidate/validate.go`: mock surface reference helper를 추가하고 `ValidateEdgeConfig`에서 호출한다.
  - [ ] `apps/edge/internal/edgevalidate/validate_test.go`: explicit mock 없는 `console.adapter: mock` 실패와 explicit mock 있는 성공 테스트를 추가한다.
  - [ ] `apps/edge/internal/edgevalidate/validate_test.go`: `openai.model_routes[].adapter: mock`에서 node ref가 explicit mock node를 가리킬 때 성공하고, mock 없는 node를 가리킬 때 실패하는 테스트를 추가한다.
  - [ ] 가능하면 같은 helper로 `a2a.adapter: mock`의 enabled case도 테스트한다.
- 중간 검증:
  - [ ] `go test -count=1 ./apps/edge/internal/edgevalidate`

## 구현 체크리스트
- [ ] REVIEW_REVIEW_MOCK-1의 mapper key conflict 수정과 테스트를 완료한다.
- [ ] REVIEW_REVIEW_MOCK-2의 surface mock validation 수정과 테스트를 완료한다.
- [ ] 중간 검증과 최종 검증 명령을 실행하고 실제 stdout/stderr를 `CODE_REVIEW-local-G06.md`에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 최종 검증
```bash
go test -count=1 ./apps/edge/internal/node ./apps/edge/internal/edgevalidate ./apps/edge/internal/transport
go test -count=1 ./packages/go/config ./apps/node/internal/adapters
rg --sort path -n 'adapter: mock|mock-echo' scripts configs apps -g '!*.pb.go'
bash scripts/e2e-smoke.sh
bash scripts/e2e-openai-ollama.sh
```

예상 결과: Go 테스트와 두 e2e가 PASS한다. `rg` 출력에는 config/script의 `adapter: mock`이 없어야 하며, 남는 `mock-echo`는 mock adapter 구현 또는 mock-specific unit test처럼 의도된 위치여야 한다.
