<!-- task=m-workspace-port-env-standardization/02+01_runtime_config_docs plan=1 tag=REVIEW_REFACTOR -->

# Plan - REVIEW_REFACTOR

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

이 plan은 `code_review_cloud_G06_0.log`의 FAIL 판정을 해결하는 좁은 follow-up이다. `CODE_REVIEW-cloud-G06.md`의 구현 에이전트 소유 섹션을 채우기 전까지 구현은 완료가 아니다. 검증 출력, 계획 대비 변경, 설계 결정을 review stub에 기록하고 active 파일을 유지한 채 리뷰 준비 상태로 보고한다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review 전용이다.

구현 중 blocker가 사용자만 결정할 수 있는 범위 변경, 사용자 소유 외부 환경/secret/서비스 준비라면 active review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거와 재개 조건을 기록한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백은 사용자 리뷰 요청이 아니며, 직접 사용자에게 질문하지 않는다.

## 배경

첫 리뷰에서 runtime/config/doc 기본 포트 변경은 대체로 적용됐지만, Edge tracked `edge.yaml` 하나가 metrics old slot을 유지했고 Control Plane HTTP 및 Edge metrics default를 고정하는 regression assertion이 빠져 있었다. 또한 review stub의 Flutter 검증 차단 사유가 현재 환경과 맞지 않았고, REFACTOR-3의 deterministic `rg` 검증도 plan의 계약 명령과 달랐다. 이 follow-up은 코드 변경 범위를 새 기능으로 넓히지 않고, 누락된 test/config/evidence만 보강한다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 채팅에서 직접 질문하거나 선택지를 제시하지 않으며, code-review가 사용자 리뷰 요청의 정당성을 판단한다.

## 분석 결과

### 읽은 파일

- `agent-task/m-workspace-port-env-standardization/02+01_runtime_config_docs/code_review_cloud_G06_0.log`
- `agent-task/m-workspace-port-env-standardization/02+01_runtime_config_docs/plan_cloud_G06_0.log`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/workspace-port-env-standardization.md`
- `agent-ops/rules/project/domain/control-plane/rules.md`
- `agent-ops/rules/project/domain/edge/rules.md`
- `agent-ops/rules/project/domain/platform-common/rules.md`
- `agent-ops/rules/project/domain/client/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/control-plane-smoke.md`
- `agent-test/local/client-smoke.md`
- `agent-test/local/edge-smoke.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-test/local/testing-smoke.md`
- `apps/edge/cmd/edge/edge.yaml`
- `apps/edge/internal/edgecmd/paths.go`
- `packages/go/config/config.go`
- `packages/go/config/config_test.go`
- `packages/go/hostsetup/templates.go`
- `packages/go/hostsetup/setup_test.go`
- `apps/control-plane/cmd/control-plane/main.go`
- `apps/control-plane/cmd/control-plane/main_test.go`

### 테스트 환경 규칙

- 선택 test_env: `local`
- `agent-test/local/rules.md`를 읽었다.
- 적용 profile: `control-plane-smoke`, `edge-smoke`, `platform-common-smoke`, `client-smoke`, `testing-smoke`
- Go quick check는 local checkout에서 실행한다.
- Flutter client 검증은 원격 runner가 기준이지만, 현재 컨테이너에도 Flutter SDK가 있으므로 local `cd apps/client && flutter test`를 evidence로 수집할 수 있다. 원격 runtime evidence는 이 follow-up의 필수 완료 조건이 아니다.
- tracked 문서와 review artifact에는 token/secret/private endpoint 원문을 쓰지 않는다.

### 테스트 커버리지 공백

- Control Plane HTTP default `0.0.0.0:18000`: source/config 변경은 있지만 Go regression assertion이 없다.
- Edge metrics default `19092`: config/default/template 변경은 있지만 `cfg.Metrics.Port`와 host setup template assertion이 없다.
- Edge tracked `apps/edge/cmd/edge/edge.yaml`: `metrics.port: 9092`가 남아 있어 config discovery에서 old slot을 실제로 사용할 수 있다.
- Flutter/Dart default: `flutter test`는 reviewer가 local에서 PASS를 확인했지만, follow-up review stub에는 구현자가 실제 stdout/stderr를 다시 기록해야 한다.

### 심볼 참조

- none

### 분할 판단

- 기존 split subtask `02+01_runtime_config_docs`의 follow-up이며 새 subtask로 분리하지 않는다.
- predecessor `01_compose_env_defaults`는 `agent-task/archive/2026/06/m-workspace-port-env-standardization/01_compose_env_defaults/complete.log`로 충족되어 있다.
- 이 follow-up은 failed review findings에만 대응하므로 sibling `03+01,02_remote_smoke_evidence`의 runtime evidence 범위를 건드리지 않는다.

### 범위 결정 근거

- 새 포트 슬롯을 추가하거나 A2A default를 바꾸지 않는다.
- Docker compose 원격 기동, field runtime smoke, Roadmap Target completion은 `03+01,02_remote_smoke_evidence` 범위로 남긴다.
- unrelated active task 변경(`m-bridge-boundary-hardening`, proto/runtime/node mapper 계열)은 읽거나 수정하지 않는다.

### 빌드 등급

- `cloud-G06`: follow-up 자체는 작지만 기존 실패가 cross-domain default/test/evidence trust 문제이며, active worktree에 다른 task 변경이 섞여 있어 범위 판별과 검증 신뢰도 확인이 필요하다.

## 구현 체크리스트

- [x] Edge tracked `edge.yaml`의 metrics old slot을 `19092`로 정렬하거나, 해당 파일이 runtime config가 아니라면 사용 경계와 이유를 코드/문서에 명확히 남긴다.
- [x] Control Plane HTTP default와 Edge metrics default를 보호하는 Go regression assertions를 추가한다.
- [x] host setup Edge templates가 metrics `19092`를 생성한다는 regression assertions를 추가한다.
- [x] plan 계약 검증 명령을 그대로 실행하고, Flutter 검증은 실제 수행 출력 또는 원격 runner가 필요한 정확한 차단 근거를 기록한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REFACTOR-1] Close default drift and regression-test gaps

문제: `code_review_cloud_G06_0.log`의 Required findings에 따르면 `apps/edge/cmd/edge/edge.yaml`은 metrics `9092`를 유지하고, `apps/control-plane/cmd/control-plane/main.go`의 HTTP default 및 `packages/go/config/config.go`의 Edge metrics default를 고정하는 tests가 없다.

해결 방법:

- `apps/edge/cmd/edge/edge.yaml`의 `metrics.port`를 `19092`로 갱신한다. 만약 이 파일이 runtime discovery 후보가 아니어야 한다면 삭제/이동 대신 현재 작업 범위에서 안전한 최소 조치로 주석이나 README/test 설명을 보강하고, 왜 old slot을 유지하는지 review stub에 적는다.
- `apps/control-plane/cmd/control-plane/main_test.go`에서 repository config 또는 `defaultConfig()` 경로의 `cfg.Server.Listen == "0.0.0.0:18000"` assertion을 추가한다.
- `packages/go/config/config_test.go`에서 minimal edge config load 시 `cfg.Metrics.Port == 19092` assertion을 추가한다.
- `packages/go/hostsetup/setup_test.go`에서 `EdgeSpec().ConfigTemplate`과 `EdgeBundleConfigTemplate()`이 `port: 19092`를 포함하는지 assertion을 추가한다.

수정 파일 및 체크리스트:

- [x] `apps/edge/cmd/edge/edge.yaml`
- [x] `apps/control-plane/cmd/control-plane/main_test.go`
- [x] `packages/go/config/config_test.go`
- [x] `packages/go/hostsetup/setup_test.go`

테스트 작성: 기존 test files에 regression assertions를 추가한다. 새 test file은 필요 없다.

중간 검증:

```bash
go test ./packages/go/config ./packages/go/hostsetup ./apps/control-plane/cmd/control-plane ./apps/edge/cmd/edge
```

기대 결과: 통과.

### [REVIEW_REFACTOR-2] Restore verification evidence trust

문제: `plan_cloud_G06_0.log`는 exact `rg`와 `cd apps/client && flutter test`를 요구했지만, archived review는 좁힌 `rg`를 기록했고 Flutter SDK missing이라고 잘못 기록했다. Reviewer rerun에서는 `command -v flutter`가 `/sdk/flutter/bin/flutter`를 반환했고 `flutter test`가 PASS했다.

해결 방법:

- 아래 최종 검증 명령을 그대로 실행하고 active `CODE_REVIEW-cloud-G06.md`에 실제 stdout/stderr를 붙인다.
- `rg` 출력의 남은 `5432/6379/8080` 값은 internal/container 예외, explicit test fixture, artifact/bootstrap `18080` substring 같은 이유로 판정하고 짧게 기록한다.
- Flutter command가 실행되면 PASS 출력을 기록한다. 실행 불가 시 먼저 `command -v flutter` 결과를 기록하고, local rules 기준 원격 runner가 필요한 정확한 사유를 적는다.

수정 파일 및 체크리스트:

- [x] `CODE_REVIEW-cloud-G06.md`

테스트 작성: 검증 증거 회복 작업이므로 새 테스트 파일은 작성하지 않는다.

중간 검증:

```bash
rg --sort path 'localhost:9080|`9080`|5432|6379|8080' agent-test/local apps/client apps/control-plane apps/edge configs packages/go Makefile scripts/dev/web.sh
command -v flutter
```

기대 결과: `rg` 잔여값이 설명 가능한 예외로만 남고, Flutter availability가 실제 환경과 일치한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/edge/cmd/edge/edge.yaml` | REVIEW_REFACTOR-1 |
| `apps/control-plane/cmd/control-plane/main_test.go` | REVIEW_REFACTOR-1 |
| `packages/go/config/config_test.go` | REVIEW_REFACTOR-1 |
| `packages/go/hostsetup/setup_test.go` | REVIEW_REFACTOR-1 |
| `CODE_REVIEW-cloud-G06.md` | REVIEW_REFACTOR-2 |

## 최종 검증

```bash
test -f agent-task/m-workspace-port-env-standardization/01_compose_env_defaults/complete.log || find agent-task/archive -path '*/m-workspace-port-env-standardization/01_compose_env_defaults/complete.log' -print -quit
go test ./packages/go/config ./packages/go/hostsetup ./apps/control-plane/cmd/control-plane ./apps/edge/cmd/edge
go test ./packages/go/... ./apps/control-plane/... ./apps/edge/...
rg --sort path 'localhost:9080|`9080`|5432|6379|8080' agent-test/local apps/client apps/control-plane apps/edge configs packages/go Makefile scripts/dev/web.sh
command -v flutter
cd apps/client && flutter test
```

기대 결과: predecessor `complete.log`가 확인되고 Go/Flutter tests가 통과한다. `rg` 잔여값은 internal/container 예외, explicit test fixture, 또는 artifact/bootstrap `18080` substring처럼 설명 가능한 항목이어야 한다.

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