<!-- task=review_followup_alignment/04_explicit_mock_resource_activation plan=0 tag=REVIEW_MOCK -->
# PLAN-local-G06: mock resource 명시 활성화
date=2026-07-06

## 목적
Node payload에 mock adapter를 항상 넣는 구조를 없애고, 필요한 리소스만 config에서 명시적으로 활성화되도록 정리한다.

## 분석 결과
- 읽은 파일: `agent-ops/rules/project/rules.md`, `agent-ops/rules/private/rules.md`, `agent-ops/rules/common/rules-roadmap.md`, `agent-ops/skills/common/router.md`, `agent-ops/skills/common/plan/SKILL.md`, `agent-test/local/rules.md`, `agent-test/local/edge-smoke.md`, `agent-test/local/node-smoke.md`, `agent-ops/rules/project/domain/edge/rules.md`, `agent-ops/rules/project/domain/node/rules.md`, `agent-ops/rules/project/domain/testing/rules.md`, `packages/go/config/config.go`, `packages/go/config/config_test.go`, `apps/edge/internal/node/mapper.go`, `apps/edge/internal/node/mapper_test.go`, `apps/edge/internal/node/store.go`, `apps/edge/internal/node/store_test.go`, `apps/edge/internal/edgevalidate/validate.go`, `apps/edge/internal/edgevalidate/validate_test.go`, `apps/edge/internal/transport/integration_test.go`, `apps/edge/internal/transport/server_test.go`, `apps/node/internal/adapters/factory.go`, `apps/node/internal/adapters/config_set.go`, `apps/node/internal/adapters/adapters_blackbox_test.go`, `apps/node/internal/adapters/factory_internal_test.go`, `proto/iop/runtime.proto`, `scripts/e2e-smoke.sh`, `scripts/e2e-openai-cli-workspace.sh`, `scripts/e2e-openai-ollama.sh`, `scripts/e2e-openai-lemonade.sh`, `scripts/e2e-openai-vllm.sh`.
- SDD 기준: runtime resource activation 정합성 follow-up이며 현재 active Milestone과 연결하지 않는다. 현재 로드맵 active Milestone은 `[스케치]` 및 구현 잠금 상태이므로 로드맵 완료 항목을 선언하지 않는다.
- 테스트 환경 규칙: local 기준. Go package tests와 fake-provider e2e smoke를 함께 사용한다.
- 테스트 커버리지 공백: Node 쪽은 empty payload에서 mock이 implicit 등록되지 않는 검증이 있으나, Edge mapper가 항상 mock을 넣는 회귀를 허용하는 테스트가 남아 있다.
- 심볼 참조: `BuildConfigPayload`, `AdaptersConf`, `NormalizeAdapters`, `ValidateConfig`, `buildAdapterIndex`.
- 분할 판단: 이 plan은 config schema, Edge mapper/validate, Node adapter contract, scripts를 함께 맞추는 cross-boundary 작업이다. 다른 세 plan과 독립적이지만 내부 난도가 있어 `G06`으로 분리한다.
- 범위 결정 근거: 사용자 결정이 확정됐다. mock은 항상 주입하지 않고 필요한 리소스에 대해서만 정확하게 활성화한다.
- 빌드 등급: `local-G06`. config schema와 Edge/Node contract, integration tests, scripts를 함께 바꾼다.

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

## 작업 항목

### REVIEW_MOCK-1. Edge payload의 implicit mock 제거와 explicit config 추가
- 문제:
  - `apps/edge/internal/node/mapper.go:31` 계열 `BuildConfigPayload`가 모든 node payload에 mock adapter를 먼저 추가한다.
  - `packages/go/config/config.go:460` 계열 `AdaptersConf`에는 `mock` config field가 없어 YAML에서 mock 활성화를 명시하는 공식 schema가 부족하다.
  - `apps/edge/internal/edgevalidate/validate.go:31` 계열 validation은 enabled adapter/provider 존재를 확인하지만 mock을 명시 adapter로 다루지 않는다.
  - `apps/edge/internal/node/mapper_test.go:225` 계열 테스트와 `apps/edge/internal/transport/server_test.go:416` 계열 테스트는 implicit mock 존재를 기대한다.
  - 일부 e2e script는 실제 provider를 테스트하면서 `console.adapter: mock`을 사용하지만 node adapters에는 mock을 명시하지 않는다.
- 해결 방법:
  - `config.AdaptersConf`에 `Mock MockConf`를 추가하고 YAML/mapstructure key를 `mock`으로 둔다.
  - `BuildConfigPayload`는 `rec.Adapters.Mock.Enabled`가 true일 때만 typed `MockAdapterConfig`를 추가한다.
  - `edgevalidate`는 명시 mock adapter를 enabled adapter index에 포함하고, mock-only test node도 의도된 경우 통과시킨다.
  - Node adapter factory 계약은 유지한다. Node는 이미 payload에 explicit mock이 있을 때만 등록하고 empty payload에서는 등록하지 않는다.
  - script/generated configs에서 `console.adapter: mock`을 쓰는 경우 해당 node에 `adapters.mock.enabled: true`를 추가한다. mock이 필요하지 않은 script는 console adapter를 실제 테스트 adapter로 바꾼다.
  - 변경 전 예:
    ```go
    adapters := []*iop.AdapterConfig{{Type: "mock", Config: &iop.AdapterConfig_Mock{Mock: &iop.MockAdapterConfig{}}}}
    ```
  - 변경 후 예:
    ```go
    if rec.Adapters.Mock.Enabled {
        adapters = append(adapters, mockAdapterConfig())
    }
    ```
- 수정 파일 및 체크리스트:
  - [ ] `packages/go/config/config.go`: `MockConf`와 `AdaptersConf.Mock` 추가. normalization/validation 영향 확인.
  - [ ] `packages/go/config/config_test.go`: mock field load, omitted default false, explicit enabled true 테스트 추가.
  - [ ] `apps/edge/internal/node/mapper.go`: implicit mock 제거, explicit mock 조건부 추가.
  - [ ] `apps/edge/internal/node/mapper_test.go`: implicit mock 기대 제거, explicit mock 테스트 유지/갱신.
  - [ ] `apps/edge/internal/edgevalidate/validate.go`: explicit mock adapter를 config validation index에 반영.
  - [ ] `apps/edge/internal/edgevalidate/validate_test.go`: mock-only 또는 console mock route가 explicit mock 없으면 실패/있으면 통과하는 케이스 추가.
  - [ ] `apps/edge/internal/transport/integration_test.go`: adapter count/expectation을 explicit mock 기준으로 갱신.
  - [ ] `apps/edge/internal/transport/server_test.go`: payload tests를 implicit 없음/explicit 있음으로 분리.
  - [ ] `apps/node/internal/adapters/*`: 기존 explicit payload 계약이 깨지지 않는지 테스트만 보강한다.
  - [ ] `scripts/e2e-smoke.sh`: mock profile의 explicit mock 유지 확인.
  - [ ] `scripts/e2e-openai-cli-workspace.sh`, `scripts/e2e-openai-ollama.sh`, `scripts/e2e-openai-lemonade.sh`, `scripts/e2e-openai-vllm.sh`: `console.adapter: mock` 사용 시 explicit mock config를 추가하거나 console adapter를 실제 adapter로 변경.
- 테스트 작성:
  - [ ] config load: `adapters.mock.enabled: true`가 `AdaptersConf.Mock.Enabled`로 로드된다.
  - [ ] Edge mapper: omitted mock config는 payload에 mock을 넣지 않는다.
  - [ ] Edge mapper: explicit mock config는 typed `MockAdapterConfig`를 넣고 legacy `Settings`를 채우지 않는다.
  - [ ] Edge validate: route/console이 mock을 참조할 때 explicit mock 없이는 실패하고 있으면 통과한다.
  - [ ] Node factory: empty payload는 여전히 mock을 등록하지 않고 explicit payload만 등록한다.
- 중간 검증:
  - [ ] `go test -count=1 ./packages/go/config ./apps/edge/internal/node ./apps/edge/internal/edgevalidate ./apps/edge/internal/transport ./apps/node/internal/adapters`
  - [ ] `rg --sort path -n 'adapter: mock|mock-echo' scripts configs apps -g '!*.pb.go'`로 mock route/config 잔여를 점검하고, 각 잔여가 explicit mock config와 짝을 이루는지 확인한다.
  - [ ] `bash scripts/e2e-smoke.sh`
  - [ ] `bash scripts/e2e-openai-ollama.sh`

## 구현 체크리스트
- [ ] REVIEW_MOCK-1의 config schema, Edge payload, validation, tests, scripts를 explicit mock 기준으로 갱신한다.
- [ ] 중간 검증 명령을 실행하고 e2e 실행 불가 시 환경 사유와 package test 결과를 `CODE_REVIEW-local-G06.md`에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 최종 검증
```bash
go test -count=1 ./packages/go/config ./apps/edge/internal/node ./apps/edge/internal/edgevalidate ./apps/edge/internal/transport ./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` 출력은 mock을 의도적으로 쓰는 위치만 보여야 하며, 해당 위치에는 같은 generated/static config 안에 explicit `mock.enabled: true`가 있어야 한다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
