<!-- task=m-workspace-port-env-standardization/03+01,02_operator_client_refs plan=0 tag=PORT_REFS -->

# Plan - PORT_REFS

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

`CODE_REVIEW-local-G06.md`의 구현 에이전트 소유 섹션 작성까지가 구현입니다. 이 task는 `01_service_defaults`와 `02+01_local_infra`의 `complete.log`가 생긴 뒤 시작하세요. 검증 출력은 실제 stdout/stderr를 붙이고, finalization과 roadmap 갱신은 code-review/runtime 책임입니다.

## 배경

service와 infra defaults가 새 포트 슬롯으로 이동해도 operator CLI, headless validation matrix, Flutter socket endpoint가 `8080`을 계속 말하면 smoke command가 drift된다. 이 subtask는 operator/client 참조를 API `18030` 기준으로 정렬하고 최종 stale-reference sweep을 수행한다. PASS 시 Milestone의 compose/env 대조와 smoke checklist 갱신 task를 완료 anchor로 넘긴다.

## 사용자 리뷰 요청 흐름

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

## Roadmap Targets

- Milestone: `agent-roadmap/phase/trading-expansion/milestones/workspace-port-env-standardization.md`
- Task ids:
  - `compose-map`: `deployments/local`, `bin/dev`, `.env.example` 계열의 API/worker/PostgreSQL/Redis host publish 값을 공통 대역 후보와 대조한다.
  - `smoke-update`: 포트 변경이 필요한 smoke command, README, local rule을 한 번에 갱신할 수 있는 체크리스트를 작성한다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/trading-expansion/milestones/workspace-port-env-standardization.md`
- `agent-ops/rules/project/domain/operations/rules.md`
- `agent-ops/rules/project/domain/client/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/operations-smoke.md`
- `agent-test/local/client-smoke.md`
- `apps/cli/internal/cli/cli.go`
- `apps/cli/internal/cli/cli_test.go`
- `apps/cli/testdata/operator/headless_validation.md`
- `apps/client/lib/src/integrations/socket/socket_endpoint.dart`
- `apps/client/test/integrations/socket/alt_socket_client_test.dart`
- `apps/client/test/integrations/socket/socket_connection_controller_test.dart`
- `bin/dev`
- `README.md`

### 테스트 환경 규칙

- test_env: `local`.
- `agent-test/local/rules.md`를 읽었다. local checkout에서 quick check를 실행하고 secret/raw endpoint 출력 금지.
- matched profiles: `agent-test/local/operations-smoke.md`, `agent-test/local/client-smoke.md`.
- apps/cli는 operations domain에 속하므로 Go CLI test는 repository layout fallback으로 `cd apps/cli && go test ./...`를 사용한다.
- client 변경 필수 검증: `cd apps/client && flutter test`.
- targeted client default endpoint 변경은 `cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart`로 충분하고, final smoke는 필요 시 전체 `cd apps/client && flutter test`로 확장한다.
- Go toolchain과 Flutter toolchain은 각각 `/config/.local/bin/go`, `/sdk/flutter/bin/flutter`에서 확인했다.

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

- CLI help example string 변경은 direct assertion이 없다. `apps/cli/internal/cli/cli_test.go`의 parse-error command URL과 `go test ./...`로 flag parsing regressions를 확인한다.
- headless validation markdown은 unit test가 없으므로 deterministic `rg`로 old API URL 제거를 확인한다.
- `AltSocketEndpoint` default port는 `apps/client/test/integrations/socket/alt_socket_client_test.dart`가 직접 검증한다.
- `socket_connection_controller_test.dart`는 explicit endpoint `9000`을 사용하므로 default port 변경을 직접 커버하지 않는다.

### 심볼 참조

- renamed/removed symbols: none.

### 분할 판단

- split policy를 평가했다. 이 subtask는 operator/client references와 최종 sweep만 담당한다.
- predecessor `01`: missing. `agent-task/m-workspace-port-env-standardization/01_service_defaults/complete.log`가 아직 없다.
- predecessor `02`: missing. `agent-task/m-workspace-port-env-standardization/02+01_local_infra/complete.log`가 아직 없다.
- task directory dependency `03+01,02_operator_client_refs`가 runtime source of truth다. 구현은 both predecessors complete 후 시작한다.

### 범위 결정 근거

- 수정 범위는 `apps/cli/**` headless command references, `apps/client/lib/src/integrations/socket/socket_endpoint.dart`, `apps/client/test/integrations/socket/alt_socket_client_test.dart`, 필요 시 `bin/dev`/`README.md`의 residual URL only.
- service defaults와 local infra host publish는 predecessor tasks가 처리한다.
- Flutter UI 화면, real API/browser runtime smoke, remote server port 변경은 범위 밖이다.

### 빌드 등급

- build/review: `local-G06`. CLI/docs/client default를 함께 정렬하지만 변경 파일은 명확하고 tests/rg로 검증 가능하다.

## 의존 관계 및 구현 순서

`01_service_defaults`와 `02+01_local_infra`의 `complete.log`가 필요하다. active 경로가 없으면 matching archive `agent-task/archive/*/*/m-workspace-port-env-standardization/{01_service_defaults,02+01_local_infra}/complete.log`를 확인한다. 둘 중 하나라도 없으면 구현하지 말고 review stub에 blocker를 기록한다.

## 구현 체크리스트

- [ ] predecessor `01_service_defaults`와 `02+01_local_infra`의 `complete.log` 존재를 확인한다.
- [ ] CLI `--api-url` help/example/test/headless matrix를 API `18030` 기준으로 갱신한다.
- [ ] Flutter `AltSocketEndpoint` default port와 default endpoint test를 `18030`으로 갱신한다.
- [ ] targeted Go/Flutter tests와 stale URL `rg` 검증을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [PORT_REFS-1] CLI API URL references

문제: `apps/cli/internal/cli/cli.go:97`, `apps/cli/internal/cli/cli_test.go:60`, `apps/cli/testdata/operator/headless_validation.md:15`와 matrix rows `32-41`이 API URL을 `ws://127.0.0.1:8080/socket`으로 보여준다.

Before:

```go
// apps/cli/internal/cli/cli.go:95-98
file := fs.String("file", "", "path to operator scenario YAML file")
apiURL := fs.String("api-url", "", "API socket URL, e.g. ws://127.0.0.1:8080/socket")
timeout := fs.Duration("timeout", 0, "per-step request timeout; overrides the scenario timeout")
output := fs.String("output", string(operator.OutputText), "output format: text or jsonl")
```

해결 방법: CLI help example, parse-error test input, headless validation run command and matrix command cells를 `ws://127.0.0.1:18030/socket`으로 바꾼다.

수정 파일 및 체크리스트:

- [ ] `apps/cli/internal/cli/cli.go`
- [ ] `apps/cli/internal/cli/cli_test.go`
- [ ] `apps/cli/testdata/operator/headless_validation.md`

테스트 작성: 기존 CLI tests를 갱신한다. 별도 신규 test는 필요 없다.

중간 검증:

```bash
cd apps/cli && go test ./...
```

기대 결과: exit code 0. Go test cache output은 허용한다.

### [PORT_REFS-2] Flutter socket endpoint default

문제: `apps/client/lib/src/integrations/socket/socket_endpoint.dart:7-8`의 `ALT_SOCKET_PORT` default가 `8080`이고, `apps/client/test/integrations/socket/alt_socket_client_test.dart:59-61`도 `8080`을 기대한다.

Before:

```dart
// apps/client/lib/src/integrations/socket/socket_endpoint.dart:5-9
static const defaultPort = int.fromEnvironment(
  'ALT_SOCKET_PORT',
  defaultValue: 8080,
);
```

해결 방법: defaultValue와 default constructor test expectations를 `18030`으로 갱신한다. `ALT_SOCKET_PORT` env key는 그대로 둔다.

수정 파일 및 체크리스트:

- [ ] `apps/client/lib/src/integrations/socket/socket_endpoint.dart`
- [ ] `apps/client/test/integrations/socket/alt_socket_client_test.dart`

테스트 작성: 기존 endpoint default test를 갱신한다. `socket_connection_controller_test.dart`는 explicit `9000` endpoint라 수정하지 않는다.

중간 검증:

```bash
cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
```

기대 결과: exit code 0. Flutter toolchain unavailable이면 blocker로 기록한다.

### [PORT_REFS-3] Final stale reference sweep

문제: split migration 후 `bin/dev`, README, CLI matrix, client endpoint 중 일부에 old API URL `8080`이 남으면 smoke command가 다시 drift된다.

Before:

```text
# current stale pattern examples
ws://127.0.0.1:8080/socket
defaultValue: 8080
```

해결 방법: targeted `rg`로 old API URL and Dart default port leftovers를 찾고, intentional exception이 아닌 항목은 수정한다. `.env.example` 계열은 현재 `find . -maxdepth 3 -name '.env*' -o -name '*env.example*'`에서 없었으므로 새 파일을 만들지 않는다.

수정 파일 및 체크리스트:

- [ ] `apps/cli/**`
- [ ] `apps/client/lib/src/integrations/socket/socket_endpoint.dart`
- [ ] `apps/client/test/integrations/socket/alt_socket_client_test.dart`
- [ ] residual only: `bin/dev`
- [ ] residual only: `README.md`

테스트 작성: 신규 test 없음. stale search가 검증이다.

중간 검증:

```bash
rg --sort path -n "127\\.0\\.0\\.1:8080|defaultValue: 8080|--api-url ws://127\\.0\\.0\\.1:8080" apps/cli apps/client/lib/src/integrations/socket apps/client/test/integrations/socket bin README.md
```

기대 결과: no output. 출력이 있으면 intentional exception 또는 추가 수정 근거를 CODE_REVIEW에 기록한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/cli/internal/cli/cli.go` | PORT_REFS-1 |
| `apps/cli/internal/cli/cli_test.go` | PORT_REFS-1 |
| `apps/cli/testdata/operator/headless_validation.md` | PORT_REFS-1 |
| `apps/client/lib/src/integrations/socket/socket_endpoint.dart` | PORT_REFS-2 |
| `apps/client/test/integrations/socket/alt_socket_client_test.dart` | PORT_REFS-2 |
| `bin/dev` | PORT_REFS-3 residual only |
| `README.md` | PORT_REFS-3 residual only |

## 최종 검증

```bash
cd apps/cli && go test ./...
cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
rg --sort path -n "127\\.0\\.0\\.1:8080|defaultValue: 8080|--api-url ws://127\\.0\\.0\\.1:8080" apps/cli apps/client/lib/src/integrations/socket apps/client/test/integrations/socket bin README.md
```

기대 결과: Go/Flutter tests exit code 0. Final `rg`는 no output이어야 한다. Flutter 전체 test는 이 targeted default endpoint change에는 필수로 두지 않지만, 구현 중 관련 client behavior를 더 건드렸다면 `cd apps/client && flutter test`로 확장한다.

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