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

# Plan - REVIEW_PORT_INFRA

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

이 follow-up은 `code_review_local_G05_0.log`의 Required 문제만 해결한다. 범위를 README와 local test rule/smoke 문서의 포트/default 설명 정렬로 제한하고, service config, compose, bin script의 기존 포트 변경은 새 Required를 해결하는 데 꼭 필요하지 않으면 건드리지 않는다.

구현 중 blocker는 active review stub의 `사용자 리뷰 요청`에 기록한다. 구현 에이전트는 직접 사용자에게 묻지 않는다.

## 배경

G05 구현은 compose host publish, `bin/infra-check`, `bin/dev`의 새 포트 변경은 반영했지만, 계획에서 요구한 README env defaults 및 Workspace Port Slots 정리가 완료되지 않았다. 또한 local test rule과 operations smoke 문서가 여전히 old runtime default `8080/8081/5432/6379`를 "현재" 값으로 설명해 포트 표준화 문서가 서로 충돌한다.

## 분석 결과

### 읽어야 할 파일

- `agent-ops/rules/project/domain/operations/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/operations-smoke.md`
- `README.md`
- `agent-task/m-workspace-port-env-standardization/02+01_local_infra/code_review_local_G05_0.log`

### 테스트 환경 규칙

- test_env: `local`.
- operations 변경 baseline은 `agent-test/local/rules.md`와 `agent-test/local/operations-smoke.md`다.
- test rule 수정이 포함되므로 루트 지침에 따라 `agent-ops/skills/common/router.md`를 읽고 test rule/update-test 라우팅 조건을 확인한다.
- local toolchain에서 shell syntax와 `rg` drift 검증을 실행한다.
- Docker CLI가 없으면 compose config 검증은 `docker unavailable; compose config not run` 출력으로 기록하되, 이는 이번 follow-up의 user-review blocker가 아니다.

### 범위 결정 근거

- 수정 범위는 `README.md`, `agent-test/local/rules.md`, `agent-test/local/operations-smoke.md`다.
- `apps/cli/**`와 `apps/client/**`의 old API references는 sibling task `03+01,02_operator_client_refs` 범위로 남긴다.
- KIS/private host, token, personal endpoint 원문은 쓰지 않는다.

### 빌드 등급

- build/review: `local-G06`. 실패 원인이 명확하고 deterministic text drift라 local follow-up으로 충분하지만, test rule 문서 수정이 포함되어 G05보다 한 단계 올린다.

## 구현 체크리스트

- [ ] `README.md`에 workspace port slots와 env defaults를 migration 완료 상태로 명시한다.
- [ ] `agent-test/local/rules.md`와 `agent-test/local/operations-smoke.md`의 "현재 runtime 기본값"을 `13030/18030/18031/15430/16330` 기준으로 갱신하고 stale migration-before wording을 제거하거나 역사적 메모로 분리한다.
- [ ] shell syntax, conditional Docker config, README/local-test-rule drift 검증을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_PORT_INFRA-1] README env defaults and port slots

문제: `README.md:117`과 `README.md:118`은 worker DB/cache env를 "local fallback 있음"으로만 설명하고, G05 계획이 요구한 Workspace Port Slots 정리가 없다.

해결 방법:

- README 환경 변수 표에서 `DATABASE_URL`과 `REDIS_URL`의 local fallback을 각각 `postgres://alt:alt@localhost:15430/alt?sslmode=disable`, `redis://localhost:16330/0`로 명시한다.
- README에 Workspace Port Slots 또는 동등한 섹션을 추가해 Flutter/web preview `13030`, API `18030`, worker `18031`, optional wire/evidence relay `19030`, PostgreSQL host publish `15430`, Redis host publish `16330`을 한눈에 볼 수 있게 정리한다.
- container 내부 PostgreSQL/Redis 포트 `5432/6379`는 service DNS/container internal port로만 남는다는 원칙을 명시한다.

수정 파일 및 체크리스트:

- [ ] `README.md`

테스트 작성: 문서 정렬 작업이라 별도 unit test는 만들지 않는다.

중간 검증:

```bash
rg --sort path -n 'Workspace Port|포트 슬롯|13030|18030|18031|19030|15430|16330|DATABASE_URL|REDIS_URL' README.md
```

기대 결과: README가 새 포트 슬롯과 env defaults를 명시한다.

### [REVIEW_PORT_INFRA-2] local test rule current defaults

문제: `agent-test/local/rules.md:24`, `agent-test/local/rules.md:36`, `agent-test/local/operations-smoke.md:28`이 old ports를 현재 runtime default 또는 pre-migration 기준으로 설명한다.

해결 방법:

- 현재 runtime 기본값 문구를 API `18030`, worker `18031`, PostgreSQL host publish `15430`, Redis host publish `16330` 기준으로 갱신한다.
- Flutter/web preview `13030`과 optional wire/evidence relay `19030`는 workspace slot으로 유지한다.
- "후보 포트로 migration하기 전까지"처럼 이미 완료된 migration을 현재 진행 중으로 보이게 하는 문구는 제거하거나, old value가 필요하면 명확히 과거 migration note로만 둔다.
- container 내부 포트 `5432/6379`는 host publish default와 구분해 설명한다.

수정 파일 및 체크리스트:

- [ ] `agent-test/local/rules.md`
- [ ] `agent-test/local/operations-smoke.md`

테스트 작성: test rule 문서 정렬 작업이라 별도 unit test는 만들지 않는다.

중간 검증:

```bash
rg --sort path -n '현재 runtime 기본값|후보 포트로 migration|8080|8081|localhost:5432|localhost:6379|18030|18031|15430|16330' agent-test/local/rules.md agent-test/local/operations-smoke.md
```

기대 결과: "현재 runtime 기본값"은 새 포트 기준이다. `8080/8081`, `localhost:5432`, `localhost:6379`, stale migration-before wording은 남지 않는다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `README.md` | REVIEW_PORT_INFRA-1 |
| `agent-test/local/rules.md` | REVIEW_PORT_INFRA-2 |
| `agent-test/local/operations-smoke.md` | REVIEW_PORT_INFRA-2 |

## 최종 검증

```bash
bash -n bin/dev bin/infra-check
if command -v docker >/dev/null 2>&1; then docker compose -f deployments/local/docker-compose.yml config; else echo "docker unavailable; compose config not run"; fi
rg --sort path -n 'Workspace Port|포트 슬롯|13030|18030|18031|19030|15430|16330|DATABASE_URL|REDIS_URL' README.md agent-test/local/rules.md agent-test/local/operations-smoke.md
rg --sort path -n '현재 runtime 기본값.*(8080|8081|5432|6379)|후보 포트로 migration하기 전|127\.0\.0\.1:8080|localhost:5432|localhost:6379|5432:5432|6379:6379|flutter run -d chrome$' README.md bin deployments/local agent-test/local/rules.md agent-test/local/operations-smoke.md
```

기대 결과: shell syntax exit code 0. Docker가 없으면 compose config는 echo로 기록한다. 세 번째 `rg`는 새 포트 문서 evidence를 출력한다. 네 번째 `rg`는 exit code 1/no output이어야 하며, old host defaults나 stale migration wording이 남지 않아야 한다.

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