# Plan - Runtime Smoke And Remote Parity ## 이 파일을 읽는 구현 에이전트에게 구현이 끝나면 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 검증 명령을 실행하고 실제 stdout/stderr를 기록한 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 최종 archive, `complete.log`, 코드리뷰 판정은 code-review 스킬 전용이다. ## 배경 현재 compose 문서는 core, db, push-proxy를 올리는 방법과 smoke 절차를 갖췄지만 실제 Docker 기동과 원격 hash parity는 아직 완료 evidence가 없다. 이 작업은 Docker-capable 환경과 remote host 접근이 필요한 실행 검증이다. smoke 실패가 compose 설정 문제로 확인될 때만 repo 파일을 최소 수정한다. ## 분석 결과 ### 읽은 파일 - `agent-roadmap/current.md` - `agent-roadmap/phase/product-foundation/PHASE.md` - `agent-roadmap/phase/product-foundation/milestones/runtime-baseline.md` - `README.md` - `docs/README.md` - `services/core/compose/README.md` - `services/core/compose/.env.example` - `services/core/compose/docker-compose.yml` - `.gitignore` ### 테스트 커버리지 공백 - `local-compose`: 기존 자동 테스트 없음. 실제 `docker compose up -d`, core ping, app HEAD, db readiness, push-proxy service/config check 출력이 evidence다. - `remote-parity`: 기존 자동 테스트 없음. local/remote `sha256sum` 출력 일치와 원격 smoke 출력이 evidence다. - compose 수정이 발생하는 경우: unit test는 없고 `docker compose config`, smoke command, `git diff --check`로 검증한다. ### 심볼 참조 none. 이 작업은 code symbol rename/remove를 하지 않는다. ### 분할 판단 split decision policy를 먼저 평가했다. shared task group은 `m-runtime-baseline`이다. - `01_source_snapshots`: upstream source snapshot 반입. 외부 git snapshot 리스크. - `02_runtime_smoke`: Docker/SSH smoke 검증. terminal-agent 리스크. 두 sibling 사이에 런타임 선행 의존성은 없다. 이 plan 내부에서는 local smoke 후 remote parity를 진행한다. ### 범위 결정 근거 이 작업은 `services/core/compose/docker-compose.yml`, `services/core/compose/.env.example`, `services/core/compose/README.md`, 그리고 원격 `~/docker/services/nexo/compose` parity 확인만 다룬다. nginx/TLS, production hardening, push credential validation, push-proxy source build 전환, 기존 다른 compose 서비스와의 병합은 범위 밖이다. 계획 작성 환경에서는 `command -v docker`가 빈 출력이었으므로 실제 완료는 Docker 사용 가능한 환경에서만 가능하다. ### 빌드 등급 build=`cloud-G07`, review=`cloud-G07`. Docker/SSH/long-running service smoke와 stdout/stderr evidence가 핵심인 terminal-agent 작업이다. ## 구현 체크리스트 - [ ] `command -v docker`, `docker compose version`, `docker info`로 Docker 실행 가능성을 확인한다. - [ ] `services/core/compose`에서 `.env`를 git 밖에 준비하고 `docker compose config`가 성공하는지 확인한다. - [ ] `docker compose up -d` 후 core ping, Mattermost app HEAD, db readiness, push-proxy service/config smoke를 실행한다. 검증: `cd services/core/compose && docker compose up -d` 후 core ping과 Mattermost 앱 접근이 성공한다. - [ ] `NEXO_REMOTE_HOST`를 사용해 원격 `~/docker/services/nexo/compose`의 `docker-compose.yml`과 `.env.example` hash가 local과 일치하는지 확인한다. 검증: local/remote compose와 `.env.example` hash 비교가 일치한다. - [ ] smoke 실패가 repo 설정 문제로 확인될 때만 compose 파일이나 README를 최소 수정하고 같은 smoke를 재실행한다. - [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. ### [SMOKE-1] Local Compose Runtime #### 문제 Milestone의 `[local-compose]`는 `agent-roadmap/phase/product-foundation/milestones/runtime-baseline.md:53`에서 미완료이고 실제 Docker 기동 evidence가 필요하다. `services/core/compose/docker-compose.yml:16`부터 db healthcheck가 있고 `services/core/compose/docker-compose.yml:47`은 core가 push-proxy를 compose DNS로 참조하지만, runtime smoke 출력은 아직 없다. #### 해결 방법 Docker-capable 환경에서 local compose를 detached mode로 올리고 README에 기록된 smoke를 실행한다. `.env`는 `services/core/compose/.env.example:1`부터 `services/core/compose/.env.example:4`를 복사해 만들되 git에 올리지 않는다. ```sh cd services/core/compose cp -n .env.example .env docker compose config docker compose up -d curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping" docker compose exec db pg_isready -U mmuser -d mattermost curl -fsSI "http://localhost:${NEXO_CORE_PORT:-18065}" docker compose ps push-proxy docker compose config | rg --fixed-strings "MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://push-proxy:8066" ``` 실패 원인이 repo 설정이면 `docker-compose.yml`, `.env.example`, `README.md` 중 필요한 파일만 수정한다. Docker daemon 부재, port collision, missing remote secret처럼 repo 밖 문제면 수정하지 말고 blocker로 기록한다. #### 수정 파일 및 체크리스트 - [ ] 필요 시 `services/core/compose/docker-compose.yml`을 최소 수정한다. - [ ] 필요 시 `services/core/compose/.env.example`을 최소 수정한다. - [ ] 필요 시 `services/core/compose/README.md`를 실제 smoke와 맞춘다. - [ ] `.env`와 `services/core/data/`는 git에 포함하지 않는다. #### 테스트 작성 테스트 파일은 작성하지 않는다. 이 항목은 runtime smoke이며 실제 Docker command 출력이 검증이다. #### 중간 검증 ```sh cd services/core/compose command -v docker docker compose version docker info docker compose config docker compose up -d curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping" docker compose exec db pg_isready -U mmuser -d mattermost curl -fsSI "http://localhost:${NEXO_CORE_PORT:-18065}" docker compose ps push-proxy docker compose config | rg --fixed-strings "MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://push-proxy:8066" ``` ### [SMOKE-2] Remote Parity #### 문제 Milestone의 `[remote-parity]`는 `agent-roadmap/phase/product-foundation/milestones/runtime-baseline.md:54`에서 미완료다. `services/core/compose/README.md:58`부터 hash 비교 절차가 있지만 실제 remote output이 없다. #### 해결 방법 원격 host를 `NEXO_REMOTE_HOST`로 받고 local/remote hash를 비교한다. 원격 파일이 의도한 배포 copy와 다르면 원격을 동기화한 뒤 같은 명령을 재실행한다. repo 파일은 local source of truth가 틀린 경우에만 수정한다. ```sh test -n "$NEXO_REMOTE_HOST" cd services/core/compose sha256sum docker-compose.yml .env.example ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && sha256sum docker-compose.yml .env.example' ``` hash가 일치하면 원격에서도 최소 smoke를 실행한다. 원격 `.env`와 runtime data는 git 밖에 있어야 한다. ```sh ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose config' ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose ps' ssh "$NEXO_REMOTE_HOST" 'curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping"' ``` #### 수정 파일 및 체크리스트 - [ ] local/remote hash output을 기록한다. - [ ] 원격 drift가 있으면 원격 sync 또는 의도적 drift 사유를 기록한다. - [ ] repo 문서가 실제 remote 기준과 다를 때만 `services/core/compose/README.md`를 수정한다. #### 테스트 작성 테스트 파일은 작성하지 않는다. 이 항목은 remote smoke이며 SSH command 출력이 검증이다. #### 중간 검증 ```sh test -n "$NEXO_REMOTE_HOST" cd services/core/compose sha256sum docker-compose.yml .env.example ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && sha256sum docker-compose.yml .env.example' ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose config' ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose ps' ssh "$NEXO_REMOTE_HOST" 'curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping"' ``` ## 의존 관계 및 구현 순서 1. SMOKE-1 local compose smoke를 먼저 수행한다. 2. SMOKE-2 remote parity와 remote smoke를 수행한다. 3. 둘 중 repo 설정 문제가 발견된 경우에만 최소 수정 후 해당 smoke부터 재실행한다. ## 수정 파일 요약 | 파일 | 항목 | | --- | --- | | `services/core/compose/docker-compose.yml` | SMOKE-1 | | `services/core/compose/.env.example` | SMOKE-1 | | `services/core/compose/README.md` | SMOKE-1, SMOKE-2 | ## 최종 검증 ```sh cd services/core/compose command -v docker docker compose version docker info docker compose config docker compose up -d curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping" docker compose exec db pg_isready -U mmuser -d mattermost curl -fsSI "http://localhost:${NEXO_CORE_PORT:-18065}" docker compose ps push-proxy docker compose config | rg --fixed-strings "MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://push-proxy:8066" test -n "$NEXO_REMOTE_HOST" sha256sum docker-compose.yml .env.example ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && sha256sum docker-compose.yml .env.example' ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose config' ssh "$NEXO_REMOTE_HOST" 'cd ~/docker/services/nexo/compose && docker compose ps' ssh "$NEXO_REMOTE_HOST" 'curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping"' cd ../../.. git status --short services/core/compose git diff --check ``` Expected outcome: Docker is available, compose config is valid, local core ping and app HEAD succeed, db is ready, push-proxy service/config smoke succeeds, remote hashes match local hashes, remote compose config and ping succeed, and `git diff --check` reports no whitespace errors. 모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.