chore(ports): 워크스페이스 포트를 표준화한다
API/worker runtime default와 local infra host publish가 같은 포트 정책을 사용하도록 맞춘다.\n\nagent-task 리뷰 산출물을 함께 남겨 포트 표준화 작업의 검토 이력을 추적할 수 있게 한다.
This commit is contained in:
parent
5488c4bc8b
commit
87c7f9cdee
23 changed files with 2096 additions and 24 deletions
23
README.md
23
README.md
|
|
@ -35,7 +35,7 @@ Flutter client는 별도 터미널에서 실행한다.
|
|||
|
||||
```bash
|
||||
cd apps/client
|
||||
flutter run -d chrome
|
||||
flutter run -d chrome --web-port 13030
|
||||
```
|
||||
|
||||
전체 검증은 루트에서 실행한다.
|
||||
|
|
@ -58,7 +58,7 @@ bin/build
|
|||
| API 실행 | `cd services/api && go run ./cmd/alt-api` | 기본 socket path는 `/socket`이다. |
|
||||
| Worker 실행 | `cd services/worker && go run ./cmd/alt-worker` | 현재는 worker scaffold 상태다. |
|
||||
| CLI 실행 | `cd apps/cli && go run ./cmd/alt` | 운영자 CLI scaffold다. |
|
||||
| Client 실행 | `cd apps/client && flutter run -d chrome` | Flutter web target 기준 개발 실행이다. |
|
||||
| Client 실행 | `cd apps/client && flutter run -d chrome --web-port 13030` | Flutter web target 기준 개발 실행이다. |
|
||||
|
||||
## 구조
|
||||
|
||||
|
|
@ -110,12 +110,25 @@ AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인
|
|||
| 이름 | 설명 | 필수 |
|
||||
|------|------|------|
|
||||
| `ALT_API_HOST` | API socket server host. 기본값 `127.0.0.1`. | 아니오 |
|
||||
| `ALT_API_PORT` | API socket server port. 기본값 `8080`. | 아니오 |
|
||||
| `ALT_API_PORT` | API socket server port. 기본값 `18030`. | 아니오 |
|
||||
| `ALT_API_SOCKET_PATH` | API WebSocket path. 기본값 `/socket`. | 아니오 |
|
||||
| `ALT_SOCKET_HEARTBEAT_INTERVAL_SEC` | proto-socket heartbeat interval. 기본값 `30`. | 아니오 |
|
||||
| `ALT_SOCKET_HEARTBEAT_WAIT_SEC` | proto-socket heartbeat wait. 기본값 `10`. | 아니오 |
|
||||
| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback 있음. | 아니오 |
|
||||
| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback 있음. | 아니오 |
|
||||
| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback: `postgres://alt:alt@localhost:15430/alt?sslmode=disable`. | 아니오 |
|
||||
| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback: `redis://localhost:16330/0`. | 아니오 |
|
||||
|
||||
## 워크스페이스 포트 슬롯
|
||||
|
||||
| 용도 | 포트 |
|
||||
|------|------|
|
||||
| Flutter/web preview | `13030` |
|
||||
| API socket server | `18030` |
|
||||
| worker socket | `18031` |
|
||||
| optional wire/evidence relay | `19030` |
|
||||
| PostgreSQL host publish | `15430` |
|
||||
| Redis host publish | `16330` |
|
||||
|
||||
PostgreSQL(`5432`)과 Redis(`6379`)의 container 내부 포트는 service DNS/container internal 통신에만 사용하며, host publish 기본값은 위 슬롯으로 통일한다.
|
||||
|
||||
## Secret 관리
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,206 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=0 tag=PORT_DEFAULTS -->
|
||||
|
||||
# Code Review Reference - PORT_DEFAULTS
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/01_service_defaults, plan=0, tag=PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [PORT_DEFAULTS-1] API config defaults | [x] |
|
||||
| [PORT_DEFAULTS-2] Worker config defaults | [x] |
|
||||
| [PORT_DEFAULTS-3] Worker README defaults | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] API config default를 API `18030`, worker socket `18031` 기준으로 갱신하고 default test를 보강한다.
|
||||
- [x] worker config default를 worker `18031`, PostgreSQL `15430`, Redis `16330` 기준으로 갱신하고 default test를 보강한다.
|
||||
- [x] `services/worker/README.md` configuration table을 새 runtime default에 맞춘다.
|
||||
- [x] `go test ./services/api/...`와 `go test ./services/worker/...`를 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_0.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G06_0.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/01_service_defaults/`로 이동한다.
|
||||
- [ ] PASS split 작업이면 이동 후 parent에 남은 sibling/file을 확인한다.
|
||||
- [x] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
|
||||
- [ ] USER_REVIEW이면 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_PLAN의 계획과 다르게 구현한 없다. 모든 변경은 PLAN이 지정한 대로 진행했다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- API `ALT_API_PORT` fallback을 `8080` → `18030`으로 변경
|
||||
- API `ALT_WORKER_SOCKET_URL` fallback을 `ws://127.0.0.1:8081/socket` → `ws://127.0.0.1:18031/socket`으로 변경
|
||||
- Worker `DATABASE_URL` fallback의 PostgreSQL port를 `5432` → `15430`으로 변경
|
||||
- Worker `REDIS_URL` fallback의 Redis port를 `6379` → `16330`으로 변경
|
||||
- Worker `ALT_WORKER_PORT` fallback을 `8081` → `18031`으로 변경
|
||||
- `TestLoadDefaultsIncludeLocalWebSocketOrigins`에 `cfg.Port`와 `cfg.WorkerSocketURL` default 검증 추가
|
||||
- `TestLoadWorkerSocketURL`의 default 기대값을 `18031`로 갱신
|
||||
- `TestConfigDefault`에 `DATABASE_URL`/`REDIS_URL` Unset 및 default 검증 추가
|
||||
- `services/worker/README.md` configuration table에 `ALT_WORKER_HOST`, `ALT_WORKER_PORT`, `ALT_WORKER_SOCKET_PATH` 항목 추가
|
||||
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- API default port와 worker URL이 `18030/18031`로 함께 이동했는지 확인한다.
|
||||
- worker DB/Redis fallback과 README table이 `15430/16330`으로 일치하는지 확인한다.
|
||||
- old defaults가 tests/intentional fixtures 외에 남았는지 `rg` 결과를 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
|
||||
### PORT_DEFAULTS-1 중간 검증
|
||||
```bash
|
||||
$ go test ./services/api/...
|
||||
? git.toki-labs.com/toki/alt/services/api/cmd/alt-api [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config 0.002s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/socket 0.010s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/workerclient (cached)
|
||||
```
|
||||
|
||||
### PORT_DEFAULTS-2 중간 검증
|
||||
```bash
|
||||
$ go test ./services/worker/...
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-data-check [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-migrate (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/backtest (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/config 0.002s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/jobs (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/datacheck (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/papertrading (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/providers/kis (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/rediskeys (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/socket 0.062s
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres/sqlc [no test files]
|
||||
```
|
||||
|
||||
### PORT_DEFAULTS-3 중간 검증
|
||||
```bash
|
||||
$ rg --sort path -n "5432|6379|8081|18031|15430|16330" services/worker/README.md services/worker/internal/config
|
||||
services/worker/README.md:47:| `DATABASE_URL` | PostgreSQL connection string | `postgres://alt:alt@localhost:15430/alt?sslmode=disable` |
|
||||
services/worker/README.md:48:| `REDIS_URL` | Redis connection string | `redis://localhost:16330/0` |
|
||||
services/worker/README.md:50:| `ALT_WORKER_PORT` | Worker listen port | `18031` |
|
||||
services/worker/internal/config/config.go:20: DatabaseURL: getenv("DATABASE_URL", "postgres://alt:alt@localhost:15430/alt?sslmode=disable"),
|
||||
services/worker/internal/config/config.go:21: RedisURL: getenv("REDIS_URL", "redis://localhost:16330/0"),
|
||||
services/worker/internal/config/config.go:25: Port: getenvInt("ALT_WORKER_PORT", 18031),
|
||||
services/worker/internal/config/config_test.go:43: if cfg.Port != 18031 {
|
||||
services/worker/internal/config/config_test.go:44: t.Errorf("expected default Port to be 18031, got %d", cfg.Port)
|
||||
services/worker/internal/config/config_test.go:49: if cfg.DatabaseURL != "postgres://alt:alt@localhost:15430/alt?sslmode=disable" {
|
||||
services/worker/internal/config/config_test.go:50: t.Errorf("expected default DatabaseURL to be postgres://alt:alt@localhost:15430/alt?sslmode=disable, got %q", cfg.DatabaseURL)
|
||||
services/worker/internal/config/config_test.go:52: if cfg.RedisURL != "redis://localhost:16330/0" {
|
||||
services/worker/internal/config/config_test.go:53: t.Errorf("expected default RedisURL to be redis://localhost:16330/0, got %q", cfg.RedisURL)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ go test ./services/api/...
|
||||
? git.toki-labs.com/toki/alt/services/api/cmd/alt-api [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config 0.002s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/contracts 0.005s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/socket 0.009s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/workerclient 0.411s
|
||||
|
||||
$ go test ./services/worker/...
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker 0.008s
|
||||
? git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-data-check [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-migrate 0.005s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/backtest 0.005s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/config 0.008s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/contracts 0.010s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/jobs 0.005s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/datacheck 0.004s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer 0.004s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/papertrading 0.005s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/providers/kis 0.034s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/rediskeys 0.003s
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/socket 0.065s
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres 0.067s
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres/sqlc [no test files]
|
||||
|
||||
$ rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
(no output — no old defaults remain in service files)
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
_리뷰 에이전트가 append한다._
|
||||
|
||||
### 2026-06-07 local-G06 review
|
||||
|
||||
- 종합 판정: FAIL
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Fail
|
||||
- test coverage: Fail
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Fail
|
||||
- 발견된 문제:
|
||||
- Required: `services/api/internal/config/config_test.go:8`의 `TestLoadDefaultsIncludeLocalWebSocketOrigins`가 `cfg.WorkerSocketURL` default를 검증하면서 `ALT_WORKER_SOCKET_URL`을 비우지 않는다. 외부 환경에 `ALT_WORKER_SOCKET_URL`이 설정되어 있으면 default 검증이 default가 아닌 외부 값을 읽고 실패한다. 실제 확인 명령 `ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config`는 `expected default WorkerSocketURL ... got "ws://example.invalid/socket"`로 실패했다. Fix: `cfg := Load()` 전에 `t.Setenv("ALT_WORKER_SOCKET_URL", "")`를 추가하거나 worker URL default assertion을 이미 env를 제어하는 `TestLoadWorkerSocketURL`에만 남긴다.
|
||||
- Nit (fixed during review): `services/worker/README.md`의 `ALT_WORKER_SOCKET_PATH` 설명이 Unix socket으로 되어 있어 WebSocket path로 정정했다.
|
||||
- 다음 단계: FAIL이므로 user-review gate 없이 후속 `PLAN-local-G07.md`와 `CODE_REVIEW-local-G07.md`를 작성한다.
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=1 tag=REVIEW_PORT_DEFAULTS -->
|
||||
|
||||
# Code Review Reference - REVIEW_PORT_DEFAULTS
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/01_service_defaults, plan=1, tag=REVIEW_PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-local-G07.md` -> `code_review_local_G07_1.log`, `PLAN-local-G07.md` -> `plan_local_G07_1.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/01_service_defaults/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_PORT_DEFAULTS-1] API default test hermeticity | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] `TestLoadDefaultsIncludeLocalWebSocketOrigins`에서 `ALT_WORKER_SOCKET_URL`을 비워 default assertion이 외부 env에 흔들리지 않게 한다.
|
||||
- [x] `ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config`, `go test ./services/api/...`, `go test ./services/worker/...`, stale default `rg` 검증을 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G07_1.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G07_1.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/m-workspace-port-env-standardization/01_service_defaults/`를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/01_service_defaults/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-workspace-port-env-standardization/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
계획과 동일하게 구현했다. 대체 명령이나 범위 변경 없음. 계획이 제시한 1차 해결 방법(`cfg := Load()` 전에 `t.Setenv("ALT_WORKER_SOCKET_URL", "")` 추가)을 그대로 적용했고, 대안(assertion 이동)은 채택하지 않았다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- `TestLoadDefaultsIncludeLocalWebSocketOrigins`는 이미 다른 default를 검증하기 위해 관련 env를 모두 비우는 패턴(`t.Setenv(..., "")`)을 쓰고 있어, worker URL default 검증도 같은 패턴으로 `ALT_WORKER_SOCKET_URL`을 비워 hermeticity를 맞췄다. 중복 assertion(default WorkerSocketURL은 `TestLoadWorkerSocketURL`에도 있음)은 유지하되 이 테스트 내에서 env를 명시적으로 제어하는 방향을 택해, default 회귀를 두 곳에서 잡는 안전망을 남겼다.
|
||||
- 수정 범위는 `services/api/internal/config/config_test.go` 한 파일로 제한했다. production config literal, worker config, worker README 등 이전 구현/리뷰에서 기준값에 맞춘 변경은 되돌리지 않았다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `TestLoadDefaultsIncludeLocalWebSocketOrigins`가 `ALT_WORKER_SOCKET_URL`을 명시적으로 비우는지 확인한다.
|
||||
- 외부 `ALT_WORKER_SOCKET_URL`을 설정한 focused command가 통과했는지 확인한다.
|
||||
- 이전 구현의 service default literal과 worker README 보정이 되돌아가지 않았는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### REVIEW_PORT_DEFAULTS-1 중간 검증
|
||||
```bash
|
||||
$ ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config 0.003s
|
||||
# exit code 0
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ go test ./services/api/...
|
||||
? git.toki-labs.com/toki/alt/services/api/cmd/alt-api [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config 0.002s
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/socket (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/workerclient (cached)
|
||||
# exit code 0
|
||||
|
||||
$ go test ./services/worker/...
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-data-check [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-migrate (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/backtest (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/config (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/jobs (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/datacheck (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/papertrading (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/providers/kis (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/rediskeys (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/socket (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres/sqlc [no test files]
|
||||
# exit code 0
|
||||
|
||||
$ rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
# no output, exit code 1 (no stale service default 남아 있지 않음)
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
_리뷰 에이전트가 append한다._
|
||||
|
||||
### 2026-06-07 local-G07 review
|
||||
|
||||
- 종합 판정: FAIL
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Fail
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Fail
|
||||
- verification trust: Pass
|
||||
- 발견된 문제:
|
||||
- Required: `README.md:113` 등 root README 변경이 이 follow-up의 명시 범위 밖인데 active diff에 남아 있고, `ALT_API_PORT`/`ALT_WORKER_SOCKET_URL`/`ALT_WORKER_PORT` 기본값을 여전히 `8080`/`8081`로 문서화한다. 실제 service default는 `services/api/internal/config/config.go`와 `services/worker/internal/config/config.go`에서 `18030`/`18031`로 바뀌었으므로, task diff에 포함된 tracked guide가 코드와 충돌한다. Fix: 이 subtask에서는 `README.md` 변경을 제거해 root guide 정렬을 후속 `operator_client_refs`/docs task로 되돌리거나, 유지해야 한다면 현재 service defaults와 충돌하지 않게 모든 값과 문장을 정확히 갱신한다. 이 task의 기존 plan은 `README.md`를 범위 밖으로 두었으므로 제거가 더 좁은 수정이다.
|
||||
- 다음 단계: FAIL이므로 user-review gate 없이 후속 `PLAN-local-G07.md`와 `CODE_REVIEW-local-G07.md`를 작성한다.
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| 섹션 | 소유자 | 설명 |
|
||||
|------|--------|------|
|
||||
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` -> `[x]` 체크만 구현 에이전트가 수행 |
|
||||
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` -> `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 진행에 사용자 입력이 필요하지 않으면 `상태: 없음` 유지 |
|
||||
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움 |
|
||||
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=2 tag=REVIEW2_PORT_DEFAULTS -->
|
||||
|
||||
# Code Review Reference - REVIEW2_PORT_DEFAULTS
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/01_service_defaults, plan=2, tag=REVIEW2_PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-local-G07.md` -> `code_review_local_G07_2.log`, `PLAN-local-G07.md` -> `plan_local_G07_2.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/01_service_defaults/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW2_PORT_DEFAULTS-1] Root README drift removal | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] root `README.md`의 active diff를 제거해 이 subtask가 root README를 변경하지 않게 한다.
|
||||
- [x] `git diff -- README.md --exit-code`, focused API config test, API/worker Go tests, stale service default `rg` 검증을 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G07_2.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G07_2.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [x] PASS이면 active task 디렉터리 `agent-task/m-workspace-port-env-standardization/01_service_defaults/`를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/01_service_defaults/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-workspace-port-env-standardization/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
계획과 동일하게 구현했다. 대체 명령이나 범위 변경 없음. `git checkout -- README.md` 같은 destructive shortcut 대신 Edit 툴로 diff에서 추가된 부분(env rows 4개, `Workspace Port Slots` 섹션)만 제거했다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- 제거 범위를 diff에서 추가된 4개의 env var 행(`ALT_WORKER_SOCKET_URL`, `ALT_WORKER_HOST`, `ALT_WORKER_PORT`, `ALT_WORKER_SOCKET_PATH`)과 `Workspace Port Slots` 섹션 전체(섹션 헤더 포함, `Port migration checklist` 까지)로 한정했다.
|
||||
- 기존 `services/api/internal/config/`, `services/worker/internal/config/`, `services/worker/README.md`의 service default 변경(18030/18031 포트)은 유지했다.
|
||||
- root README의 최종 포트 가이드 정렬은 계획대로 후속 `operator_client_refs`/docs task 범위로 남겼다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `git diff -- README.md --exit-code`가 통과해 root README drift가 제거됐는지 확인한다.
|
||||
- service config/test/default 변경이 되돌아가지 않았는지 확인한다.
|
||||
- focused API config test와 stale service default `rg`가 통과했는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### REVIEW2_PORT_DEFAULTS-1 중간 검증
|
||||
```bash
|
||||
$ git diff -- README.md --exit-code
|
||||
# no output, exit code 0
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config (cached)
|
||||
# exit code 0
|
||||
|
||||
$ go test ./services/api/...
|
||||
? git.toki-labs.com/toki/alt/services/api/cmd/alt-api [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/config (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/socket (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/api/internal/workerclient (cached)
|
||||
# exit code 0
|
||||
|
||||
$ go test ./services/worker/...
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-data-check [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-migrate (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/backtest (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/config (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/contracts (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/jobs (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/datacheck (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/papertrading (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/providers/kis (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/rediskeys (cached)
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/socket (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage [no test files]
|
||||
ok git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres (cached)
|
||||
? git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres/sqlc [no test files]
|
||||
# exit code 0
|
||||
|
||||
$ rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
# no output, exit code 1 (stale default 없음)
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
_리뷰 에이전트가 append한다._
|
||||
|
||||
### 2026-06-07 local-G07 review
|
||||
|
||||
- 종합 판정: PASS
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Pass
|
||||
- 발견된 문제: 없음
|
||||
- 다음 단계: PASS이므로 `complete.log`를 작성하고 task 디렉터리를 archive로 이동한다.
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| 섹션 | 소유자 | 설명 |
|
||||
| ---------------------------------------------------------| ---------------------------------------------| ----------------------------------------------------------------------------|
|
||||
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` -> `[x]` 체크만 구현 에이전트가 수행 |
|
||||
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` -> `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 진행에 사용자 입력이 필요하지 않으면 `상태: 없음` 유지 |
|
||||
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움 |
|
||||
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# Complete - m-workspace-port-env-standardization/01_service_defaults
|
||||
|
||||
## 완료 일시
|
||||
|
||||
2026-06-07
|
||||
|
||||
## 요약
|
||||
|
||||
Service runtime defaults를 workspace 후보 포트로 정렬하고, 3회 리뷰 루프 끝에 PASS로 종료했다.
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_local_G06_0.log` | `code_review_local_G06_0.log` | FAIL | API default test가 외부 `ALT_WORKER_SOCKET_URL` 환경변수에 오염되는 문제가 발견되어 follow-up 생성 |
|
||||
| `plan_local_G07_1.log` | `code_review_local_G07_1.log` | FAIL | G07 test hermeticity는 해결됐으나 root `README.md` 범위 밖 diff가 남아 follow-up 생성 |
|
||||
| `plan_local_G07_2.log` | `code_review_local_G07_2.log` | PASS | root `README.md` drift 제거, service defaults/tests/docs 검증 통과 |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- API config default를 API `18030`, worker socket `18031` 기준으로 변경했다.
|
||||
- Worker config default를 worker `18031`, PostgreSQL `15430`, Redis `16330` 기준으로 변경했다.
|
||||
- API/worker config default tests를 보강하고 API default test의 env hermeticity를 보완했다.
|
||||
- `services/worker/README.md` configuration table을 service default와 일치하도록 정리했다.
|
||||
- 이 subtask 범위 밖인 root `README.md` diff를 제거했다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `git diff -- README.md --exit-code` - PASS; no output.
|
||||
- `ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config` - PASS; `ok git.toki-labs.com/toki/alt/services/api/internal/config`.
|
||||
- `go test ./services/api/...` - PASS; all API packages passed.
|
||||
- `go test ./services/worker/...` - PASS; all worker packages passed or reported `[no test files]`.
|
||||
- `rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md` - PASS; no stale service default matches, exit code 1.
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=0 tag=PORT_DEFAULTS -->
|
||||
|
||||
# Plan - PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-local-G06.md`의 구현 에이전트 소유 섹션 작성까지가 구현입니다. 변경 후 검증을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 리뷰를 요청하세요. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 없이는 직접 질문하지 말고 `사용자 리뷰 요청` 섹션에 근거를 남깁니다. 최종 archive, `complete.log`, roadmap 갱신은 code-review/runtime 책임입니다.
|
||||
|
||||
## 배경
|
||||
|
||||
현재 API/worker runtime default는 `8080/8081/5432/6379`이고, Milestone은 backend `18030/18031`, DB/cache `15430/16330` 후보를 표준화하려 한다. service default를 먼저 바꿔야 compose/bin과 CLI/client 문서가 같은 기준을 바라볼 수 있다. 이 subtask는 service config와 service-local tests만 다룬다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 blocker는 active `CODE_REVIEW-local-G06.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 사용자에게 직접 질문하지 않고, code-review가 해당 요청을 검증해 필요할 때만 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 읽은 파일
|
||||
|
||||
- `agent-roadmap/current.md`
|
||||
- `agent-roadmap/phase/trading-expansion/PHASE.md`
|
||||
- `agent-roadmap/phase/trading-expansion/milestones/workspace-port-env-standardization.md`
|
||||
- `agent-ops/rules/project/domain/api/rules.md`
|
||||
- `agent-ops/rules/project/domain/worker/rules.md`
|
||||
- `agent-test/local/rules.md`
|
||||
- `agent-test/local/api-smoke.md`
|
||||
- `agent-test/local/worker-smoke.md`
|
||||
- `services/api/internal/config/config.go`
|
||||
- `services/api/internal/config/config_test.go`
|
||||
- `services/worker/internal/config/config.go`
|
||||
- `services/worker/internal/config/config_test.go`
|
||||
- `services/worker/README.md`
|
||||
|
||||
### 테스트 환경 규칙
|
||||
|
||||
- test_env: `local`.
|
||||
- `agent-test/local/rules.md`를 읽었다. local quick check는 현재 checkout에서 실행하고, raw secret/personal endpoint 출력 금지.
|
||||
- matched profiles: `agent-test/local/api-smoke.md`, `agent-test/local/worker-smoke.md`.
|
||||
- API 작은 변경 필수 검증: `go test ./services/api/...`.
|
||||
- worker 작은 변경 필수 검증: `go test ./services/worker/...`.
|
||||
- storage SQL 변경은 없으므로 `bin/worker-storage-check`는 대상이 아니다.
|
||||
- `<확인 필요>` 값 없음. Go toolchain은 `/config/.local/bin/go`에서 확인했다.
|
||||
|
||||
### 테스트 커버리지 공백
|
||||
|
||||
- API default worker URL 변경은 `services/api/internal/config/config_test.go`가 직접 검증한다. API port default는 현재 직접 assertion이 없으므로 이 plan에서 추가한다.
|
||||
- worker port default 변경은 `services/worker/internal/config/config_test.go`가 검증한다.
|
||||
- worker DB/Redis fallback 변경은 현재 직접 assertion이 없으므로 이 plan에서 추가한다.
|
||||
|
||||
### 심볼 참조
|
||||
|
||||
- renamed/removed symbols: none.
|
||||
|
||||
### 분할 판단
|
||||
|
||||
- split policy를 먼저 평가했다. 전체 migration은 service runtime defaults, operations infra/bin, operator/client references가 다른 ownership과 검증 경로를 가진다.
|
||||
- shared task group: `m-workspace-port-env-standardization`.
|
||||
- `01_service_defaults`: API/worker config와 service-local tests. depends_on=[].
|
||||
- `02+01_local_infra`: compose/bin/README 정렬. depends_on=[01].
|
||||
- `03+01,02_operator_client_refs`: CLI/client URL 참조와 최종 stale reference sweep. depends_on=[01,02].
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 이 subtask는 `services/api/internal/config/**`, `services/worker/internal/config/**`, `services/worker/README.md`만 수정한다.
|
||||
- `deployments/local/**`, `bin/**`, root `README.md`, CLI/client URL 참조는 후속 split task에서 수정한다.
|
||||
- proto-socket contracts, worker storage migrations, Flutter UI는 포트 default 변경 범위를 벗어난다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- build/review: `local-G06`. 두 service config를 건드리지만 변경은 fallback literal과 tests에 국한되고 검증이 deterministic하다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] API config default를 API `18030`, worker socket `18031` 기준으로 갱신하고 default test를 보강한다.
|
||||
- [ ] worker config default를 worker `18031`, PostgreSQL `15430`, Redis `16330` 기준으로 갱신하고 default test를 보강한다.
|
||||
- [ ] `services/worker/README.md` configuration table을 새 runtime default에 맞춘다.
|
||||
- [ ] `go test ./services/api/...`와 `go test ./services/worker/...`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [PORT_DEFAULTS-1] API config defaults
|
||||
|
||||
문제: `services/api/internal/config/config.go:22-27`이 API port `8080`과 worker socket `8081`을 fallback으로 사용한다. `services/api/internal/config/config_test.go:44-45`도 worker URL default를 `8081`로 기대하고, API port default assertion은 없다.
|
||||
|
||||
Before:
|
||||
|
||||
```go
|
||||
// services/api/internal/config/config.go:21-27
|
||||
Host: getenv("ALT_API_HOST", "127.0.0.1"),
|
||||
Port: getenvInt("ALT_API_PORT", 8080),
|
||||
SocketPath: getenv("ALT_API_SOCKET_PATH", "/socket"),
|
||||
HeartbeatIntervalSec: getenvInt("ALT_SOCKET_HEARTBEAT_INTERVAL_SEC", 30),
|
||||
HeartbeatWaitSec: getenvInt("ALT_SOCKET_HEARTBEAT_WAIT_SEC", 10),
|
||||
WSOriginPatterns: getenvList("ALT_API_WS_ORIGIN_PATTERNS", "localhost:*,127.0.0.1:*"),
|
||||
WorkerSocketURL: getenv("ALT_WORKER_SOCKET_URL", "ws://127.0.0.1:8081/socket"),
|
||||
```
|
||||
|
||||
해결 방법: `ALT_API_PORT` fallback을 `18030`으로, `ALT_WORKER_SOCKET_URL` fallback을 `ws://127.0.0.1:18031/socket`으로 바꾼다. `TestLoadDefaultsIncludeLocalWebSocketOrigins` 또는 별도 default test에서 `cfg.Port == 18030`과 worker URL default를 검증한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `services/api/internal/config/config.go`
|
||||
- [ ] `services/api/internal/config/config_test.go`
|
||||
|
||||
테스트 작성: 기존 config test에 default assertion을 추가한다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
go test ./services/api/...
|
||||
```
|
||||
|
||||
기대 결과: exit code 0. Go test cache output은 허용한다.
|
||||
|
||||
### [PORT_DEFAULTS-2] Worker config defaults
|
||||
|
||||
문제: `services/worker/internal/config/config.go:20-25`가 DB/cache host fallback `5432/6379`, worker socket `8081`을 사용한다. `services/worker/internal/config/config_test.go:41-42`는 worker port `8081`만 확인하고 DB/Redis fallback은 확인하지 않는다.
|
||||
|
||||
Before:
|
||||
|
||||
```go
|
||||
// services/worker/internal/config/config.go:20-25
|
||||
DatabaseURL: getenv("DATABASE_URL", "postgres://alt:alt@localhost:5432/alt?sslmode=disable"),
|
||||
RedisURL: getenv("REDIS_URL", "redis://localhost:6379/0"),
|
||||
RedisKeyPrefix: getenv("ALT_REDIS_KEY_PREFIX", "alt"),
|
||||
WorkerQueue: getenv("ALT_WORKER_QUEUE", "default"),
|
||||
Host: getenv("ALT_WORKER_HOST", "127.0.0.1"),
|
||||
Port: getenvInt("ALT_WORKER_PORT", 8081),
|
||||
```
|
||||
|
||||
해결 방법: fallback을 `postgres://alt:alt@localhost:15430/alt?sslmode=disable`, `redis://localhost:16330/0`, worker port `18031`로 갱신한다. default test에서 세 값을 모두 검증한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `services/worker/internal/config/config.go`
|
||||
- [ ] `services/worker/internal/config/config_test.go`
|
||||
|
||||
테스트 작성: 기존 `TestConfigDefault`에 `DatabaseURL`, `RedisURL`, `Port` assertion을 둔다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
go test ./services/worker/...
|
||||
```
|
||||
|
||||
기대 결과: exit code 0. Go test cache output은 허용한다.
|
||||
|
||||
### [PORT_DEFAULTS-3] Worker README defaults
|
||||
|
||||
문제: `services/worker/README.md:47-48`가 worker DB/Redis defaults를 `5432/6379`로 문서화한다.
|
||||
|
||||
Before:
|
||||
|
||||
```markdown
|
||||
<!-- services/worker/README.md:47-48 -->
|
||||
| `DATABASE_URL` | PostgreSQL connection string | `postgres://alt:alt@localhost:5432/alt?sslmode=disable` |
|
||||
| `REDIS_URL` | Redis connection string | `redis://localhost:6379/0` |
|
||||
```
|
||||
|
||||
해결 방법: configuration table을 `15430/16330` fallback으로 바꾸고, worker socket env rows가 없으면 `ALT_WORKER_HOST`, `ALT_WORKER_PORT`, `ALT_WORKER_SOCKET_PATH`를 추가한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `services/worker/README.md`
|
||||
|
||||
테스트 작성: README 문서 변경이라 별도 test는 쓰지 않는다. `rg`로 stale defaults를 검증한다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
rg --sort path -n "5432|6379|8081|18031|15430|16330" services/worker/README.md services/worker/internal/config
|
||||
```
|
||||
|
||||
기대 결과: old default `5432/6379/8081`은 intentionally retained test fixtures 외 service README/config fallback에 남지 않는다.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `services/api/internal/config/config.go` | PORT_DEFAULTS-1 |
|
||||
| `services/api/internal/config/config_test.go` | PORT_DEFAULTS-1 |
|
||||
| `services/worker/internal/config/config.go` | PORT_DEFAULTS-2 |
|
||||
| `services/worker/internal/config/config_test.go` | PORT_DEFAULTS-2 |
|
||||
| `services/worker/README.md` | PORT_DEFAULTS-3 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
go test ./services/api/...
|
||||
go test ./services/worker/...
|
||||
rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
```
|
||||
|
||||
기대 결과: 두 `go test` 명령은 exit code 0. 마지막 `rg`는 migration 후 의도치 않은 old service default가 없음을 보여야 하며, 남는 항목이 있으면 CODE_REVIEW에 intentional exception으로 설명한다.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=1 tag=REVIEW_PORT_DEFAULTS -->
|
||||
|
||||
# Plan - REVIEW_PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-local-G07.md`의 구현 에이전트 소유 섹션 작성까지가 구현입니다. 변경 후 검증을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 리뷰를 요청하세요. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 없이는 직접 질문하지 말고 `사용자 리뷰 요청` 섹션에 근거를 남깁니다. 최종 archive, `complete.log`, roadmap 갱신은 code-review/runtime 책임입니다.
|
||||
|
||||
## 배경
|
||||
|
||||
이전 리뷰(`code_review_local_G06_0.log`)에서 service default literal 자체는 계획과 맞는 것으로 확인했지만, API default test가 외부 `ALT_WORKER_SOCKET_URL` 환경변수에 오염되는 결함이 발견되었다. 이 follow-up은 해당 test hermeticity만 고친다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 blocker는 active `CODE_REVIEW-local-G07.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 사용자에게 직접 질문하지 않고, code-review가 해당 요청을 검증해 필요할 때만 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 근거
|
||||
|
||||
- archived review: `agent-task/m-workspace-port-env-standardization/01_service_defaults/code_review_local_G06_0.log`
|
||||
- 실패 재현:
|
||||
|
||||
```bash
|
||||
ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
```
|
||||
|
||||
실패 요지: `TestLoadDefaultsIncludeLocalWebSocketOrigins`가 worker URL default를 기대하면서 `ALT_WORKER_SOCKET_URL`을 비우지 않아 외부 env 값을 읽는다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 수정 대상은 `services/api/internal/config/config_test.go`로 제한한다.
|
||||
- production config literal, worker config, worker README는 이미 이전 구현과 리뷰 중 보정으로 기준값에 맞아 있으므로 되돌리지 않는다.
|
||||
- `deployments/local/**`, `bin/**`, root `README.md`, CLI/client URL 참조는 이 subtask 범위가 아니다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- build/review: `local-G07`. 결함이 명확하고 deterministic 재현 명령이 있으며, follow-up은 API config test 한 파일의 hermeticity 보강이다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] `TestLoadDefaultsIncludeLocalWebSocketOrigins`에서 `ALT_WORKER_SOCKET_URL`을 비워 default assertion이 외부 env에 흔들리지 않게 한다.
|
||||
- [ ] `ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config`, `go test ./services/api/...`, `go test ./services/worker/...`, stale default `rg` 검증을 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [REVIEW_PORT_DEFAULTS-1] API default test hermeticity
|
||||
|
||||
문제: `services/api/internal/config/config_test.go:8`의 `TestLoadDefaultsIncludeLocalWebSocketOrigins`가 `cfg.WorkerSocketURL` default를 검증하면서 `ALT_WORKER_SOCKET_URL`을 비우지 않는다. 외부 환경에 해당 env가 있으면 default 검증이 외부 값을 읽고 실패한다.
|
||||
|
||||
Before:
|
||||
|
||||
```go
|
||||
t.Setenv("ALT_API_WS_ORIGIN_PATTERNS", "")
|
||||
|
||||
cfg := Load()
|
||||
```
|
||||
|
||||
해결 방법: `cfg := Load()` 전에 `t.Setenv("ALT_WORKER_SOCKET_URL", "")`를 추가한다. 대안으로 worker URL default assertion을 `TestLoadWorkerSocketURL`에만 남길 수 있지만, 중복 assertion을 유지한다면 반드시 이 테스트 안에서 env를 제어한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `services/api/internal/config/config_test.go`
|
||||
|
||||
테스트 작성: 기존 테스트 보강만 수행한다. 새 테스트 파일은 만들지 않는다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
```
|
||||
|
||||
기대 결과: exit code 0. 외부 env가 있어도 default test가 `t.Setenv("ALT_WORKER_SOCKET_URL", "")`로 격리되어 통과한다.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `services/api/internal/config/config_test.go` | REVIEW_PORT_DEFAULTS-1 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
go test ./services/api/...
|
||||
go test ./services/worker/...
|
||||
rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
```
|
||||
|
||||
기대 결과: 세 `go test` 명령은 exit code 0. 마지막 `rg`는 exit code 1/no output으로 old service default가 남지 않았음을 보여야 한다.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<!-- task=m-workspace-port-env-standardization/01_service_defaults plan=2 tag=REVIEW2_PORT_DEFAULTS -->
|
||||
|
||||
# Plan - REVIEW2_PORT_DEFAULTS
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-local-G07.md`의 구현 에이전트 소유 섹션 작성까지가 구현입니다. 변경 후 검증을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 리뷰를 요청하세요. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 없이는 직접 질문하지 말고 `사용자 리뷰 요청` 섹션에 근거를 남깁니다. 최종 archive, `complete.log`, roadmap 갱신은 code-review/runtime 책임입니다.
|
||||
|
||||
## 배경
|
||||
|
||||
이전 리뷰(`code_review_local_G07_1.log`)에서 G07의 API config test hermeticity 수정과 필수 검증은 통과했다. 남은 문제는 active diff에 root `README.md` 변경이 포함되어 있다는 점이다. 이 subtask의 계획은 root README를 범위 밖으로 두었고, 해당 README 변경은 현재 service default와도 충돌하므로 이번 follow-up은 root README drift만 제거한다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 blocker는 active `CODE_REVIEW-local-G07.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 사용자에게 직접 질문하지 않고, code-review가 해당 요청을 검증해 필요할 때만 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 근거
|
||||
|
||||
- archived review: `agent-task/m-workspace-port-env-standardization/01_service_defaults/code_review_local_G07_1.log`
|
||||
- 현재 문제: `README.md` diff가 이 task 범위 밖인데 active diff에 남아 있고, root guide에 `8080/8081` 기본값을 추가/유지해 service config의 `18030/18031` 변경과 충돌한다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 수정 대상은 root `README.md`의 active diff 제거로 제한한다.
|
||||
- `services/api/internal/config/config.go`, `services/api/internal/config/config_test.go`, `services/worker/internal/config/config.go`, `services/worker/internal/config/config_test.go`, `services/worker/README.md`의 기존 service-default 변경은 유지한다.
|
||||
- root README의 최종 포트 가이드 정렬은 후속 `operator_client_refs`/docs task에서 다룬다. 이 subtask에서는 out-of-scope root README diff를 남기지 않는 것이 가장 좁은 수정이다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- build/review: `local-G07`. 변경은 문서 drift 제거와 deterministic 검증에 한정된다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] root `README.md`의 active diff를 제거해 이 subtask가 root README를 변경하지 않게 한다.
|
||||
- [ ] `git diff -- README.md --exit-code`, focused API config test, API/worker Go tests, stale service default `rg` 검증을 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [REVIEW2_PORT_DEFAULTS-1] Root README drift removal
|
||||
|
||||
문제: root `README.md` 변경은 이 subtask의 계획 범위 밖이다. 특히 추가된 env rows와 `Workspace Port Slots` 문구는 service config가 이미 `18030/18031`로 바뀐 상태에서 `8080/8081`을 현재 기본값처럼 남겨 guide와 code를 충돌시킨다.
|
||||
|
||||
해결 방법: `README.md`의 active diff를 제거한다. 안전하게 `git diff -- README.md`로 변경 범위를 확인한 뒤, 이 task에서 추가된 env rows와 `Workspace Port Slots` section을 apply_patch로 제거해 `git diff -- README.md --exit-code`가 통과하게 한다. `git checkout -- README.md` 같은 destructive shortcut은 사용하지 않는다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `README.md`
|
||||
|
||||
테스트 작성: 문서 drift 제거라 새 테스트는 쓰지 않는다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
git diff -- README.md --exit-code
|
||||
```
|
||||
|
||||
기대 결과: exit code 0, no output.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `README.md` | REVIEW2_PORT_DEFAULTS-1 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
git diff -- README.md --exit-code
|
||||
ALT_WORKER_SOCKET_URL=ws://example.invalid/socket go test ./services/api/internal/config
|
||||
go test ./services/api/...
|
||||
go test ./services/worker/...
|
||||
rg --sort path -n "127\\.0\\.0\\.1:8081|localhost:5432|localhost:6379|ALT_WORKER_PORT.*8081" services/api/internal/config services/worker/internal/config services/worker/README.md
|
||||
```
|
||||
|
||||
기대 결과: `git diff -- README.md --exit-code`와 세 `go test` 명령은 exit code 0. 마지막 `rg`는 exit code 1/no output으로 old service default가 남지 않았음을 보여야 한다.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
<!-- task=m-workspace-port-env-standardization/02+01_local_infra plan=0 tag=PORT_INFRA -->
|
||||
|
||||
# Code Review Reference - PORT_INFRA
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Start only after predecessor `01_service_defaults` has `complete.log`.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> Do not ask the user directly during implementation; record blockers in `사용자 리뷰 요청`.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/02+01_local_infra, plan=0, tag=PORT_INFRA
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [PORT_INFRA-1] Compose host publish | [x] |
|
||||
| [PORT_INFRA-2] infra-check defaults | [x] |
|
||||
| [PORT_INFRA-3] dev and README entrypoints | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] predecessor `01_service_defaults`의 `complete.log` 존재를 확인한다.
|
||||
- [x] compose host publish를 PostgreSQL `15430:5432`, Redis `16330:6379`로 바꾼다.
|
||||
- [x] `bin/infra-check` default URL과 default-branch comparison 문자열을 `15430/16330`으로 맞춘다.
|
||||
- [x] `bin/dev`와 `README.md`의 실행 안내를 API `18030`, Flutter preview `13030`, DB/cache `15430/16330` 기준으로 갱신한다.
|
||||
- [x] `bash -n`, conditional Docker config, `rg` drift 검증을 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G05_0.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G05_0.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block을 확인한다.
|
||||
- [ ] PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다.
|
||||
- [ ] PASS split 작업이면 parent에 남은 sibling/file을 확인한다.
|
||||
- [x] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
|
||||
- [ ] USER_REVIEW이면 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
없음. 계획과 동일하게 구현했다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- predecessor `01_service_defaults` complete.log는 archive 경로(`agent-task/archive/2026/06/m-workspace-port-env-standardization/01_service_defaults/complete.log`)에서 확인했다. CLAUDE.md split subtask 예외 조항 적용.
|
||||
- `bin/infra-check`의 equality comparison 문자열(line 53, 60)도 default URL과 함께 갱신했다. 두 값이 불일치하면 환경변수 미설정 시 항상 external branch로 빠지는 버그가 생기므로 동시 갱신이 필수다.
|
||||
- README.md 환경변수 테이블의 `ALT_API_PORT` 기본값을 `8080` → `18030`으로 갱신했다. flutter run 명령에 `--web-port 13030`을 추가했다(quick start 섹션 line 38, command table line 61).
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- predecessor `01_service_defaults` 완료 근거가 확인되었는지 본다.
|
||||
- compose host side만 바뀌고 container 내부 포트는 유지되었는지 확인한다.
|
||||
- Docker 부재 시 검증 미실행이 정확히 기록되었는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 명령의 실제 stdout/stderr를 붙인다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
|
||||
### PORT_INFRA-1 중간 검증
|
||||
```bash
|
||||
$ 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
|
||||
docker unavailable; compose config not run
|
||||
```
|
||||
|
||||
Docker CLI가 PATH에 없으므로 compose runtime 검증은 미실행. infra runtime 미검증 위험 기록.
|
||||
|
||||
### PORT_INFRA-2 중간 검증
|
||||
```bash
|
||||
$ bash -n bin/infra-check
|
||||
(no output, exit 0)
|
||||
|
||||
$ rg --sort path -n "localhost:15430|localhost:16330|localhost:5432|localhost:6379" bin/infra-check
|
||||
7:database_url="${DATABASE_URL:-postgres://alt:alt@localhost:15430/alt?sslmode=disable}"
|
||||
8:redis_url="${REDIS_URL:-redis://localhost:16330/0}"
|
||||
53:if [ "$database_url" = "postgres://alt:alt@localhost:15430/alt?sslmode=disable" ]; then
|
||||
60:if [ "$redis_url" = "redis://localhost:16330/0" ]; then
|
||||
```
|
||||
|
||||
old defaults(`5432`/`6379`) 잔존 없음.
|
||||
|
||||
### PORT_INFRA-3 중간 검증
|
||||
```bash
|
||||
$ bash -n bin/dev
|
||||
(no output, exit 0)
|
||||
|
||||
$ rg --sort path -n "13030|18030|15430|16330|8080|5432|6379" bin/dev README.md
|
||||
bin/dev:22: cd apps/cli && go run ./cmd/alt operator scenario run --file testdata/operator/market_data_status_query.yaml --api-url ws://127.0.0.1:18030/socket --output jsonl
|
||||
bin/dev:25: cd apps/client && flutter run -d chrome --web-port 13030
|
||||
README.md:38:flutter run -d chrome --web-port 13030
|
||||
README.md:61:| Client 실행 | `cd apps/client && flutter run -d chrome --web-port 13030` | Flutter web target 기준 개발 실행이다. |
|
||||
README.md:113:| `ALT_API_PORT` | API socket server port. 기본값 `18030`. | 아니오 |
|
||||
```
|
||||
|
||||
새 포트 기준으로만 언급. old defaults(`8080`/`5432`/`6379`) 잔존 없음.
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ bash -n bin/dev bin/infra-check
|
||||
(no output, exit 0)
|
||||
|
||||
$ 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
|
||||
docker unavailable; compose config not run
|
||||
|
||||
$ rg --sort path -n "5432:5432|6379:6379|127\\.0\\.0\\.1:8080|localhost:5432|localhost:6379|flutter run -d chrome$" deployments/local bin README.md
|
||||
(no output)
|
||||
```
|
||||
|
||||
의도치 않은 old operations defaults 잔존 없음. Docker 부재로 compose runtime/config 검증 미실행은 infra runtime 미검증 위험으로 기록한다.
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
_리뷰 에이전트가 append한다._
|
||||
|
||||
### 2026-06-07 리뷰 판정
|
||||
|
||||
- 종합 판정: FAIL
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Fail
|
||||
- test coverage: Fail
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Fail
|
||||
- verification trust: Fail
|
||||
- 발견된 문제:
|
||||
- Required: `README.md:117`과 `README.md:118`은 여전히 `DATABASE_URL`/`REDIS_URL`을 "local fallback 있음"으로만 설명하고, 계획의 PORT_INFRA-3가 요구한 README env defaults 및 Workspace Port Slots 정리를 완료하지 않았다. `DATABASE_URL=postgres://alt:alt@localhost:15430/alt?sslmode=disable`, `REDIS_URL=redis://localhost:16330/0`, API/worker `18030/18031`, Flutter `13030`, DB/cache `15430/16330`, optional wire `19030`을 README에서 같은 기준으로 명시하고 container internal port 유지 원칙을 함께 적어야 한다.
|
||||
- Required: `agent-test/local/rules.md:24`, `agent-test/local/rules.md:36`, `agent-test/local/operations-smoke.md:28`은 service/compose/bin defaults가 이미 `18030/18031/15430/16330`으로 이동했는데도 "현재 runtime 기본값"을 `8080/8081/5432/6379`로 기록한다. operations smoke 기준상 runtime default/host publish migration은 local test rule과 smoke 문서의 포트 설명도 같은 작업에서 대조해야 하므로, 현재 기본값 문구를 새 포트로 갱신하고 migration-before wording을 제거하거나 역사적 메모로 분리해야 한다.
|
||||
- 다음 단계: user-review gate는 트리거하지 않는다. active plan/review를 archive한 뒤 `PLAN-local-G06.md`와 `CODE_REVIEW-local-G06.md` follow-up을 작성한다.
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
<!-- task=m-workspace-port-env-standardization/02+01_local_infra plan=1 tag=REVIEW_PORT_INFRA -->
|
||||
|
||||
# Code Review Reference - REVIEW_PORT_INFRA
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/02+01_local_infra, plan=1, tag=REVIEW_PORT_INFRA
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-local-G06.md` -> `code_review_local_G06_1.log`, `PLAN-local-G06.md` -> `plan_local_G06_1.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_PORT_INFRA-1] README env defaults and port slots | [x] |
|
||||
| [REVIEW_PORT_INFRA-2] local test rule current defaults | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [x] `README.md`에 workspace port slots와 env defaults를 migration 완료 상태로 명시한다.
|
||||
- [x] `agent-test/local/rules.md`와 `agent-test/local/operations-smoke.md`의 "현재 runtime 기본값"을 `13030/18030/18031/15430/16330` 기준으로 갱신하고 stale migration-before wording을 제거하거나 역사적 메모로 분리한다.
|
||||
- [x] shell syntax, conditional Docker config, README/local-test-rule drift 검증을 실행한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_1.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G06_1.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [x] PASS이면 active task 디렉터리 `agent-task/m-workspace-port-env-standardization/02+01_local_infra/`를 `agent-task/archive/YYYY/MM/m-workspace-port-env-standardization/02+01_local_infra/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [x] PASS이고 task group이 `m-workspace-port-env-standardization`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-workspace-port-env-standardization/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
없음. 계획과 동일하게 구현했다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- **REVIEW_PORT_INFRA-1**: README 환경 변수 테이블의 `DATABASE_URL`/`REDIS_URL` 설명을 "local fallback 있음" → 실제 URL 명시로 교체했다. "## 워크스페이스 포트 슬롯" 섹션을 환경 변수 테이블 바로 뒤에 삽입해 Flutter `13030`, API `18030`, worker `18031`, optional wire `19030`, PostgreSQL host `15430`, Redis host `16330`, container internal port 원칙(`5432/6379`은 service DNS/internal 전용)을 일괄 명시했다.
|
||||
- **REVIEW_PORT_INFRA-2**: `agent-test/local/rules.md` line 24의 현재 runtime 기본값 문구를 `8080/8081/5432/6379` → `18030/18031/15430/16330`으로 교체했다. line 34의 "workspace 후보 포트" → "workspace 포트 슬롯"으로 갱신, line 36의 "후보 포트로 migration하기 전까지" 문구를 제거하고 현재 기본값 기준으로 재작성했다. `agent-test/local/operations-smoke.md` line 28도 같은 기준으로 업데이트했다.
|
||||
- `update-test` SKILL 절차에 따라 `.gitignore`에 `agent-test/local/`이 이미 등록(line 41)된 것을 확인했다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- README가 DB/cache env fallback과 workspace port slot을 새 기준으로 명시하는지 확인한다.
|
||||
- local test rule/smoke 문서가 old runtime defaults를 현재값으로 말하지 않는지 확인한다.
|
||||
- `apps/cli/**`와 `apps/client/**` old API references는 sibling task 범위로 남겨 두었는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다.
|
||||
|
||||
### REVIEW_PORT_INFRA-1 중간 검증
|
||||
```bash
|
||||
$ rg --sort path -n 'Workspace Port|포트 슬롯|13030|18030|18031|19030|15430|16330|DATABASE_URL|REDIS_URL' README.md
|
||||
README.md:38:flutter run -d chrome --web-port 13030
|
||||
README.md:61:| Client 실행 | `cd apps/client && flutter run -d chrome --web-port 13030` | Flutter web target 기준 개발 실행이다. |
|
||||
README.md:113:| `ALT_API_PORT` | API socket server port. 기본값 `18030`. | 아니오 |
|
||||
README.md:117:| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback: `postgres://alt:alt@localhost:15430/alt?sslmode=disable`. | 아니오 |
|
||||
README.md:118:| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback: `redis://localhost:16330/0`. | 아니오 |
|
||||
README.md:120:## 워크스페이스 포트 슬롯
|
||||
README.md:124:| Flutter/web preview | `13030` |
|
||||
README.md:125:| API socket server | `18030` |
|
||||
README.md:126:| worker socket | `18031` |
|
||||
README.md:127:| optional wire/evidence relay | `19030` |
|
||||
README.md:128:| PostgreSQL host publish | `15430` |
|
||||
README.md:129:| Redis host publish | `16330` |
|
||||
```
|
||||
|
||||
### REVIEW_PORT_INFRA-2 중간 검증
|
||||
```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
|
||||
agent-test/local/rules.md:24:- port: 현재 runtime 기본값은 API socket `18030`, worker socket `18031`, PostgreSQL host publish `15430`, Redis host publish `16330`이다.
|
||||
agent-test/local/rules.md:34:- workspace 포트 슬롯: Flutter/web preview `13030`, backend API/worker `18030/18031`, optional wire/evidence relay `19030`, DB/cache host publish `15430/16330`.
|
||||
agent-test/local/rules.md:36:- 실행 가능한 command와 테스트 판정은 현재 runtime 기본값 `18030/18031/15430/16330`을 기준으로 기록한다.
|
||||
agent-test/local/operations-smoke.md:28:- port: 현재 runtime 기본값은 API `18030`, worker `18031`, PostgreSQL host publish `15430`, Redis host publish `16330`; workspace 포트 슬롯: frontend `13030`, API/worker `18030/18031`, optional wire `19030`, DB/cache `15430/16330`.
|
||||
```
|
||||
|
||||
`8080/8081`, `localhost:5432`, `localhost:6379`, stale migration-before wording 잔존 없음.
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ bash -n bin/dev bin/infra-check
|
||||
(no output, exit 0)
|
||||
|
||||
$ 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
|
||||
docker unavailable; compose config not run
|
||||
|
||||
$ 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
|
||||
README.md:38:flutter run -d chrome --web-port 13030
|
||||
README.md:61:| Client 실행 | `cd apps/client && flutter run -d chrome --web-port 13030` | Flutter web target 기준 개발 실행이다. |
|
||||
README.md:113:| `ALT_API_PORT` | API socket server port. 기본값 `18030`. | 아니오 |
|
||||
README.md:117:| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback: `postgres://alt:alt@localhost:15430/alt?sslmode=disable`. | 아니오 |
|
||||
README.md:118:| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback: `redis://localhost:16330/0`. | 아니오 |
|
||||
README.md:120:## 워크스페이스 포트 슬롯
|
||||
README.md:124:| Flutter/web preview | `13030` |
|
||||
README.md:125:| API socket server | `18030` |
|
||||
README.md:126:| worker socket | `18031` |
|
||||
README.md:127:| optional wire/evidence relay | `19030` |
|
||||
README.md:128:| PostgreSQL host publish | `15430` |
|
||||
README.md:129:| Redis host publish | `16330` |
|
||||
agent-test/local/rules.md:24:- port: 현재 runtime 기본값은 API socket `18030`, worker socket `18031`, PostgreSQL host publish `15430`, Redis host publish `16330`이다.
|
||||
agent-test/local/rules.md:34:- workspace 포트 슬롯: Flutter/web preview `13030`, backend API/worker `18030/18031`, optional wire/evidence relay `19030`, DB/cache host publish `15430/16330`.
|
||||
agent-test/local/rules.md:36:- 실행 가능한 command와 테스트 판정은 현재 runtime 기본값 `18030/18031/15430/16330`을 기준으로 기록한다.
|
||||
agent-test/local/operations-smoke.md:28:- port: 현재 runtime 기본값은 API `18030`, worker `18031`, PostgreSQL host publish `15430`, Redis host publish `16330`; workspace 포트 슬롯: frontend `13030`, API/worker `18030/18031`, optional wire `19030`, DB/cache `15430/16330`.
|
||||
|
||||
$ 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
|
||||
(no output)
|
||||
```
|
||||
|
||||
old host defaults 및 stale migration wording 잔존 없음. Docker 부재로 compose config 검증 미실행(echo 출력으로 기록).
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
Sections and their ownership:
|
||||
|
||||
| 섹션 | 소유자 | 설명 |
|
||||
|------|--------|------|
|
||||
| 헤더 주석, 개요(date/task/plan/tag), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` -> `[x]` 체크만 구현 에이전트가 수행 |
|
||||
| 구현 체크리스트 (항목 텍스트/순서) | follow-up plan에서 복사해 스텁 생성 시 고정 | 구현 에이전트가 `[ ]` -> `[x]` 체크만 수행; 마지막 체크박스는 저장 전 필수 |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | 구현 에이전트가 채움 | placeholder 텍스트를 실제 내용으로 교체 |
|
||||
| 사용자 리뷰 요청 | 구현 에이전트가 채움 | 진행에 사용자 입력이 필요하지 않으면 `상태: 없음` 유지 |
|
||||
| 리뷰어를 위한 체크포인트 | 스텁 생성 시 고정 | 계획에서 추출한 리뷰 포인트 |
|
||||
| 검증 결과 (섹션 제목 + 명령) | 스텁 생성 시 고정 | 실행 출력만 구현 에이전트가 채움 |
|
||||
| 코드리뷰 결과 | 리뷰 에이전트가 append | 스텁에 포함하지 않음 |
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
### 2026-06-07 리뷰 판정
|
||||
|
||||
- 종합 판정: PASS
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Pass
|
||||
- 발견된 문제: 없음
|
||||
- 다음 단계: active plan/review를 archive하고 `complete.log` 작성 후 split task directory를 `agent-task/archive/2026/06/m-workspace-port-env-standardization/02+01_local_infra/`로 이동한다. `m-workspace-port-env-standardization` 완료 이벤트 메타데이터를 보고하고 roadmap은 수정하지 않는다.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Complete - m-workspace-port-env-standardization/02+01_local_infra
|
||||
|
||||
## 완료 일시
|
||||
|
||||
2026-06-07
|
||||
|
||||
## 요약
|
||||
|
||||
Local infra, operator entrypoint, README, and local test rule port/default documentation were aligned with the workspace port slots after 2 review loops; final verdict PASS.
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_local_G05_0.log` | `code_review_local_G05_0.log` | FAIL | README env defaults/port slot documentation and local test rule current defaults were incomplete |
|
||||
| `plan_local_G06_1.log` | `code_review_local_G06_1.log` | PASS | README fallback URLs, workspace port slots, and local test rule/smoke current defaults were aligned |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- `deployments/local/docker-compose.yml` host publish ports now use PostgreSQL `15430:5432` and Redis `16330:6379`.
|
||||
- `bin/infra-check` defaults and default-branch comparisons now use `localhost:15430` and `localhost:16330`.
|
||||
- `bin/dev` and root `README.md` now show API `18030` and Flutter preview `13030`.
|
||||
- Root `README.md` now documents DB/cache local fallback URLs and the workspace port slots, while preserving container internal `5432/6379` as service DNS/internal-only ports.
|
||||
- `agent-test/local/rules.md` and `agent-test/local/operations-smoke.md` now describe current runtime defaults as `18030/18031/15430/16330`.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `bash -n bin/dev bin/infra-check` - PASS; no output, exit 0.
|
||||
- `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` - PASS for conditional check; output `docker unavailable; compose config not run`.
|
||||
- `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` - PASS; output shows README fallback URLs/port slots and local test rule/smoke defaults.
|
||||
- `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` - PASS; no output, exit 1 as expected.
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
<!-- task=m-workspace-port-env-standardization/02+01_local_infra plan=0 tag=PORT_INFRA -->
|
||||
|
||||
# Plan - PORT_INFRA
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-local-G05.md`의 구현 에이전트 소유 섹션 작성까지가 구현입니다. 이 task는 `01_service_defaults`의 `complete.log`가 생긴 뒤 시작하세요. 검증 출력은 실제 stdout/stderr를 붙이고, finalization은 code-review가 처리합니다.
|
||||
|
||||
## 배경
|
||||
|
||||
service defaults가 새 슬롯으로 이동하면 local compose host publish와 workspace helper docs도 같은 포트 정책을 말해야 한다. 이 subtask는 local infra와 operator entrypoint 문서를 정렬하되, CLI/client code references는 후속 task에 둔다. Docker가 없는 환경에서는 compose runtime 확인이 차단될 수 있으므로 syntax와 config-level 검증을 분리한다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 blocker는 active review stub의 `사용자 리뷰 요청`에 기록한다. 구현 에이전트는 직접 사용자에게 묻지 않는다.
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 읽은 파일
|
||||
|
||||
- `agent-roadmap/current.md`
|
||||
- `agent-roadmap/phase/trading-expansion/milestones/workspace-port-env-standardization.md`
|
||||
- `agent-ops/rules/project/domain/operations/rules.md`
|
||||
- `agent-test/local/rules.md`
|
||||
- `agent-test/local/operations-smoke.md`
|
||||
- `deployments/local/docker-compose.yml`
|
||||
- `bin/infra-check`
|
||||
- `bin/dev`
|
||||
- `README.md`
|
||||
|
||||
### 테스트 환경 규칙
|
||||
|
||||
- test_env: `local`.
|
||||
- `agent-test/local/rules.md`와 `agent-test/local/operations-smoke.md`를 읽었다.
|
||||
- operations 변경 baseline: helper scripts 변경 시 해당 command 직접 실행 또는 dry-run에 준하는 검증, local infra 변경 시 Docker 가능 여부 기록.
|
||||
- Docker CLI는 현재 PATH에서 발견되지 않았다. plan은 `command -v docker` 결과와 conditional `docker compose config` 검증을 요구한다.
|
||||
- `.gitignore`의 Agent-Ops block은 이미 task artifact를 unignore한다.
|
||||
|
||||
### 테스트 커버리지 공백
|
||||
|
||||
- `deployments/local/docker-compose.yml` host publish 변경은 unit test가 없으므로 `docker compose config` 또는 Docker 부재 blocker 기록이 필요하다.
|
||||
- `bin/infra-check` fallback 문자열 변경은 shell syntax와 `rg` drift 검증으로 확인한다. 실제 health check는 Docker daemon/services가 필요하다.
|
||||
- README/bin/dev 문서 변경은 command output test가 없으므로 `bash -n`과 `rg`로 확인한다.
|
||||
|
||||
### 심볼 참조
|
||||
|
||||
- renamed/removed symbols: none.
|
||||
|
||||
### 분할 판단
|
||||
|
||||
- split policy를 평가했다. 이 subtask는 operations surface만 다루며, service defaults가 선행되어야 한다.
|
||||
- predecessor `01`: missing. `agent-task/m-workspace-port-env-standardization/01_service_defaults/complete.log`가 아직 없다.
|
||||
- task directory dependency `02+01_local_infra`가 runtime source of truth다. 구현은 predecessor complete 후 시작한다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 수정 범위는 `deployments/local/docker-compose.yml`, `bin/infra-check`, `bin/dev`, `README.md`.
|
||||
- `services/**` defaults는 `01_service_defaults`, `apps/cli/**`와 `apps/client/**` references는 `03+01,02_operator_client_refs`에서 처리한다.
|
||||
- 원격 서버 배포 포트 즉시 변경과 private host/secret 기록은 범위 밖이다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- build/review: `local-G05`. shell/compose/docs 변경이지만 코드 path가 짧고 검증은 syntax/config/rg 중심이다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
`01_service_defaults`가 `complete.log`를 남긴 뒤 시작한다. 만족 경로는 `agent-task/m-workspace-port-env-standardization/01_service_defaults/complete.log` 또는 matching archive `agent-task/archive/*/*/m-workspace-port-env-standardization/01_service_defaults/complete.log`다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] predecessor `01_service_defaults`의 `complete.log` 존재를 확인한다.
|
||||
- [ ] compose host publish를 PostgreSQL `15430:5432`, Redis `16330:6379`로 바꾼다.
|
||||
- [ ] `bin/infra-check` default URL과 default-branch comparison 문자열을 `15430/16330`으로 맞춘다.
|
||||
- [ ] `bin/dev`와 `README.md`의 실행 안내를 API `18030`, Flutter preview `13030`, DB/cache `15430/16330` 기준으로 갱신한다.
|
||||
- [ ] `bash -n`, conditional Docker config, `rg` drift 검증을 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
### [PORT_INFRA-1] Compose host publish
|
||||
|
||||
문제: `deployments/local/docker-compose.yml:9`와 `deployments/local/docker-compose.yml:21`이 host publish를 `5432:5432`, `6379:6379`로 둔다.
|
||||
|
||||
Before:
|
||||
|
||||
```yaml
|
||||
# deployments/local/docker-compose.yml:8-9
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
# deployments/local/docker-compose.yml:20-21
|
||||
ports:
|
||||
- "6379:6379"
|
||||
```
|
||||
|
||||
해결 방법: host side만 `15430`과 `16330`으로 바꾸고 container 내부 포트는 `5432/6379`로 유지한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `deployments/local/docker-compose.yml`
|
||||
|
||||
테스트 작성: compose YAML 변경이라 별도 unit test는 없다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
기대 결과: Docker가 있으면 exit code 0. Docker가 없으면 echo 출력과 함께 CODE_REVIEW에 infra runtime 미검증 위험을 기록한다.
|
||||
|
||||
### [PORT_INFRA-2] infra-check defaults
|
||||
|
||||
문제: `bin/infra-check:7-8`, `bin/infra-check:53`, `bin/infra-check:60`이 default DB/cache host URLs를 `5432/6379`로 비교한다.
|
||||
|
||||
Before:
|
||||
|
||||
```bash
|
||||
# bin/infra-check:7-8
|
||||
database_url="${DATABASE_URL:-postgres://alt:alt@localhost:5432/alt?sslmode=disable}"
|
||||
redis_url="${REDIS_URL:-redis://localhost:6379/0}"
|
||||
```
|
||||
|
||||
해결 방법: default URL과 equality comparison을 `localhost:15430`, `localhost:16330`으로 갱신한다. compose default branch는 계속 Docker compose service health를 검사한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `bin/infra-check`
|
||||
|
||||
테스트 작성: shell script라 unit test 대신 syntax와 string drift 검증을 사용한다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
bash -n bin/infra-check
|
||||
rg --sort path -n "localhost:15430|localhost:16330|localhost:5432|localhost:6379" bin/infra-check
|
||||
```
|
||||
|
||||
기대 결과: `bash -n` exit code 0. `rg` 출력은 새 defaults와 intentional absence/presence를 설명 가능해야 한다.
|
||||
|
||||
### [PORT_INFRA-3] dev and README entrypoints
|
||||
|
||||
문제: `bin/dev:22`는 API URL `ws://127.0.0.1:8080/socket`, `bin/dev:25`는 unspecified Flutter port를 보여준다. `README.md:38`, `README.md:61`, `README.md:113-126`도 현재 default와 후보를 분리해 적고 있어 migration 후 최신 실행값으로 정리해야 한다.
|
||||
|
||||
Before:
|
||||
|
||||
```bash
|
||||
# bin/dev:21-25
|
||||
Operator headless scenarios (see apps/cli/testdata/operator/headless_validation.md):
|
||||
cd apps/cli && go run ./cmd/alt operator scenario validate --file testdata/operator/market_data_status_query.yaml
|
||||
cd apps/cli && go run ./cmd/alt operator scenario run --file testdata/operator/market_data_status_query.yaml --api-url ws://127.0.0.1:8080/socket --output jsonl
|
||||
|
||||
Client:
|
||||
cd apps/client && flutter run -d chrome
|
||||
```
|
||||
|
||||
해결 방법: `bin/dev`의 API URL을 `18030`, Flutter command를 `flutter run -d chrome --web-port 13030`로 바꾼다. README quick start, command table, env defaults, Workspace Port Slots를 migration 완료 상태로 갱신한다.
|
||||
|
||||
수정 파일 및 체크리스트:
|
||||
|
||||
- [ ] `bin/dev`
|
||||
- [ ] `README.md`
|
||||
|
||||
테스트 작성: docs/script output 변경이라 별도 unit test는 없다.
|
||||
|
||||
중간 검증:
|
||||
|
||||
```bash
|
||||
bash -n bin/dev
|
||||
rg --sort path -n "13030|18030|15430|16330|8080|5432|6379" bin/dev README.md
|
||||
```
|
||||
|
||||
기대 결과: `bash -n` exit code 0. README의 old defaults는 migration note나 intentional historical context 외 남지 않아야 한다.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `deployments/local/docker-compose.yml` | PORT_INFRA-1 |
|
||||
| `bin/infra-check` | PORT_INFRA-2 |
|
||||
| `bin/dev` | PORT_INFRA-3 |
|
||||
| `README.md` | PORT_INFRA-3 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```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 "5432:5432|6379:6379|127\\.0\\.0\\.1:8080|localhost:5432|localhost:6379|flutter run -d chrome$" deployments/local bin README.md
|
||||
```
|
||||
|
||||
기대 결과: shell syntax exit code 0. Docker가 없으면 compose runtime/config 검증은 blocker/risk로 기록한다. 마지막 `rg`는 의도치 않은 old operations defaults가 없음을 보여야 하며, 남는 항목은 intentional exception으로 설명한다.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
<!-- 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<!-- task=m-workspace-port-env-standardization/03+01,02_operator_client_refs plan=0 tag=PORT_REFS -->
|
||||
|
||||
# Code Review Reference - PORT_REFS
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Start only after predecessors `01_service_defaults` and `02+01_local_infra` have `complete.log`.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> Do not ask the user directly during implementation; record blockers in `사용자 리뷰 요청`.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-07
|
||||
task=m-workspace-port-env-standardization/03+01,02_operator_client_refs, plan=0, tag=PORT_REFS
|
||||
|
||||
## 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
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [PORT_REFS-1] CLI API URL references | [ ] |
|
||||
| [PORT_REFS-2] Flutter socket endpoint default | [ ] |
|
||||
| [PORT_REFS-3] Final stale reference sweep | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 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의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_0.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_local_G06_0.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block을 확인한다.
|
||||
- [ ] PASS이면 `complete.log` 작성 후 active task 디렉터리를 archive로 이동한다.
|
||||
- [ ] PASS이고 task group이 `m-workspace-port-env-standardization`이면 완료 이벤트 메타데이터를 보고하고 roadmap 수정은 runtime에 맡긴다.
|
||||
- [ ] PASS split 작업이면 parent에 남은 sibling/file을 확인한다.
|
||||
- [ ] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
|
||||
- [ ] USER_REVIEW이면 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- predecessors 01/02 완료 근거가 확인되었는지 본다.
|
||||
- `Roadmap Targets`가 Milestone task ids `compose-map`, `smoke-update`와 정확히 일치하는지 확인한다.
|
||||
- final `rg`가 old API URL/default port leftovers를 남기지 않는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 명령의 실제 stdout/stderr를 붙인다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다.
|
||||
|
||||
### PORT_REFS-1 중간 검증
|
||||
```bash
|
||||
$ cd apps/cli && go test ./...
|
||||
(output)
|
||||
```
|
||||
|
||||
### PORT_REFS-2 중간 검증
|
||||
```bash
|
||||
$ cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
|
||||
(output)
|
||||
```
|
||||
|
||||
### PORT_REFS-3 중간 검증
|
||||
```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
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ cd apps/cli && go test ./...
|
||||
(output)
|
||||
|
||||
$ cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
|
||||
(output)
|
||||
|
||||
$ 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
|
||||
(output)
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
_리뷰 에이전트가 append한다._
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<!-- 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
4
bin/dev
4
bin/dev
|
|
@ -19,8 +19,8 @@ ALT development entrypoints:
|
|||
|
||||
Operator headless scenarios (see apps/cli/testdata/operator/headless_validation.md):
|
||||
cd apps/cli && go run ./cmd/alt operator scenario validate --file testdata/operator/market_data_status_query.yaml
|
||||
cd apps/cli && go run ./cmd/alt operator scenario run --file testdata/operator/market_data_status_query.yaml --api-url ws://127.0.0.1:8080/socket --output jsonl
|
||||
cd apps/cli && go run ./cmd/alt operator scenario run --file testdata/operator/market_data_status_query.yaml --api-url ws://127.0.0.1:18030/socket --output jsonl
|
||||
|
||||
Client:
|
||||
cd apps/client && flutter run -d chrome
|
||||
cd apps/client && flutter run -d chrome --web-port 13030
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ set -euo pipefail
|
|||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
compose_file="$root/deployments/local/docker-compose.yml"
|
||||
|
||||
database_url="${DATABASE_URL:-postgres://alt:alt@localhost:5432/alt?sslmode=disable}"
|
||||
redis_url="${REDIS_URL:-redis://localhost:6379/0}"
|
||||
database_url="${DATABASE_URL:-postgres://alt:alt@localhost:15430/alt?sslmode=disable}"
|
||||
redis_url="${REDIS_URL:-redis://localhost:16330/0}"
|
||||
|
||||
docker_cmd=""
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
|
|
@ -50,14 +50,14 @@ check_external_redis() {
|
|||
|
||||
echo "ALT infrastructure health"
|
||||
|
||||
if [ "$database_url" = "postgres://alt:alt@localhost:5432/alt?sslmode=disable" ]; then
|
||||
if [ "$database_url" = "postgres://alt:alt@localhost:15430/alt?sslmode=disable" ]; then
|
||||
check_default_postgres
|
||||
else
|
||||
check_external_postgres
|
||||
fi
|
||||
echo "postgres: ok"
|
||||
|
||||
if [ "$redis_url" = "redis://localhost:6379/0" ]; then
|
||||
if [ "$redis_url" = "redis://localhost:16330/0" ]; then
|
||||
check_default_redis
|
||||
else
|
||||
check_external_redis
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ services:
|
|||
POSTGRES_USER: alt
|
||||
POSTGRES_PASSWORD: alt
|
||||
ports:
|
||||
- "5432:5432"
|
||||
- "15430:5432"
|
||||
volumes:
|
||||
- alt_postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
|
|
@ -18,7 +18,7 @@ services:
|
|||
redis:
|
||||
image: redis:7
|
||||
ports:
|
||||
- "6379:6379"
|
||||
- "16330:6379"
|
||||
volumes:
|
||||
- alt_redis:/data
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ type Config struct {
|
|||
func Load() Config {
|
||||
return Config{
|
||||
Host: getenv("ALT_API_HOST", "127.0.0.1"),
|
||||
Port: getenvInt("ALT_API_PORT", 8080),
|
||||
Port: getenvInt("ALT_API_PORT", 18030),
|
||||
SocketPath: getenv("ALT_API_SOCKET_PATH", "/socket"),
|
||||
HeartbeatIntervalSec: getenvInt("ALT_SOCKET_HEARTBEAT_INTERVAL_SEC", 30),
|
||||
HeartbeatWaitSec: getenvInt("ALT_SOCKET_HEARTBEAT_WAIT_SEC", 10),
|
||||
WSOriginPatterns: getenvList("ALT_API_WS_ORIGIN_PATTERNS", "localhost:*,127.0.0.1:*"),
|
||||
WorkerSocketURL: getenv("ALT_WORKER_SOCKET_URL", "ws://127.0.0.1:8081/socket"),
|
||||
WorkerSocketURL: getenv("ALT_WORKER_SOCKET_URL", "ws://127.0.0.1:18031/socket"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,20 @@ func TestLoadDefaultsIncludeLocalWebSocketOrigins(t *testing.T) {
|
|||
t.Setenv("ALT_SOCKET_HEARTBEAT_INTERVAL_SEC", "")
|
||||
t.Setenv("ALT_SOCKET_HEARTBEAT_WAIT_SEC", "")
|
||||
t.Setenv("ALT_API_WS_ORIGIN_PATTERNS", "")
|
||||
t.Setenv("ALT_WORKER_SOCKET_URL", "")
|
||||
|
||||
cfg := Load()
|
||||
|
||||
// Verify API port default
|
||||
if cfg.Port != 18030 {
|
||||
t.Errorf("expected default Port to be 18030, got %d", cfg.Port)
|
||||
}
|
||||
|
||||
// Verify worker socket URL default
|
||||
if cfg.WorkerSocketURL != "ws://127.0.0.1:18031/socket" {
|
||||
t.Errorf("expected default WorkerSocketURL to be ws://127.0.0.1:18031/socket, got %q", cfg.WorkerSocketURL)
|
||||
}
|
||||
|
||||
want := []string{"localhost:*", "127.0.0.1:*"}
|
||||
if !reflect.DeepEqual(cfg.WSOriginPatterns, want) {
|
||||
t.Fatalf("WSOriginPatterns = %v, want %v", cfg.WSOriginPatterns, want)
|
||||
|
|
@ -41,7 +52,7 @@ func TestLoadWorkerSocketURL(t *testing.T) {
|
|||
|
||||
t.Setenv("ALT_WORKER_SOCKET_URL", "")
|
||||
cfg = Load()
|
||||
if cfg.WorkerSocketURL != "ws://127.0.0.1:8081/socket" {
|
||||
t.Errorf("expected default WorkerSocketURL to be ws://127.0.0.1:8081/socket, got %q", cfg.WorkerSocketURL)
|
||||
if cfg.WorkerSocketURL != "ws://127.0.0.1:18031/socket" {
|
||||
t.Errorf("expected default WorkerSocketURL to be ws://127.0.0.1:18031/socket, got %q", cfg.WorkerSocketURL)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ Environment variables can be used to customize worker runtime:
|
|||
|
||||
| Variable | Description | Default |
|
||||
|---|---|---|
|
||||
| `DATABASE_URL` | PostgreSQL connection string | `postgres://alt:alt@localhost:5432/alt?sslmode=disable` |
|
||||
| `REDIS_URL` | Redis connection string | `redis://localhost:6379/0` |
|
||||
| `DATABASE_URL` | PostgreSQL connection string | `postgres://alt:alt@localhost:15430/alt?sslmode=disable` |
|
||||
| `REDIS_URL` | Redis connection string | `redis://localhost:16330/0` |
|
||||
| `ALT_WORKER_HOST` | Worker bind host | `127.0.0.1` |
|
||||
| `ALT_WORKER_PORT` | Worker listen port | `18031` |
|
||||
| `ALT_WORKER_SOCKET_PATH` | Worker WebSocket path | `/socket` |
|
||||
| `ALT_REDIS_KEY_PREFIX` | Namespace prefix for Redis keys | `alt` |
|
||||
| `ALT_WORKER_QUEUE` | Target worker queue to consume from | `default` |
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ type Config struct {
|
|||
|
||||
func Load() Config {
|
||||
return Config{
|
||||
DatabaseURL: getenv("DATABASE_URL", "postgres://alt:alt@localhost:5432/alt?sslmode=disable"),
|
||||
RedisURL: getenv("REDIS_URL", "redis://localhost:6379/0"),
|
||||
DatabaseURL: getenv("DATABASE_URL", "postgres://alt:alt@localhost:15430/alt?sslmode=disable"),
|
||||
RedisURL: getenv("REDIS_URL", "redis://localhost:16330/0"),
|
||||
RedisKeyPrefix: getenv("ALT_REDIS_KEY_PREFIX", "alt"),
|
||||
WorkerQueue: getenv("ALT_WORKER_QUEUE", "default"),
|
||||
Host: getenv("ALT_WORKER_HOST", "127.0.0.1"),
|
||||
Port: getenvInt("ALT_WORKER_PORT", 8081),
|
||||
Port: getenvInt("ALT_WORKER_PORT", 18031),
|
||||
SocketPath: getenv("ALT_WORKER_SOCKET_PATH", "/socket"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,16 +32,24 @@ func TestConfigDefault(t *testing.T) {
|
|||
os.Unsetenv("ALT_WORKER_HOST")
|
||||
os.Unsetenv("ALT_WORKER_PORT")
|
||||
os.Unsetenv("ALT_WORKER_SOCKET_PATH")
|
||||
os.Unsetenv("DATABASE_URL")
|
||||
os.Unsetenv("REDIS_URL")
|
||||
|
||||
cfg := Load()
|
||||
|
||||
if cfg.Host != "127.0.0.1" {
|
||||
t.Errorf("expected default Host to be 127.0.0.1, got %q", cfg.Host)
|
||||
}
|
||||
if cfg.Port != 8081 {
|
||||
t.Errorf("expected default Port to be 8081, got %d", cfg.Port)
|
||||
if cfg.Port != 18031 {
|
||||
t.Errorf("expected default Port to be 18031, got %d", cfg.Port)
|
||||
}
|
||||
if cfg.SocketPath != "/socket" {
|
||||
t.Errorf("expected default SocketPath to be /socket, got %q", cfg.SocketPath)
|
||||
}
|
||||
if cfg.DatabaseURL != "postgres://alt:alt@localhost:15430/alt?sslmode=disable" {
|
||||
t.Errorf("expected default DatabaseURL to be postgres://alt:alt@localhost:15430/alt?sslmode=disable, got %q", cfg.DatabaseURL)
|
||||
}
|
||||
if cfg.RedisURL != "redis://localhost:16330/0" {
|
||||
t.Errorf("expected default RedisURL to be redis://localhost:16330/0, got %q", cfg.RedisURL)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue