---
test_env: dev
last_rule_updated_at: 2026-08-02
---

# dev 테스트 규칙

**현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
**dev 테스트 환경은 local 테스트 조건을 그대로 따르되, 같은 원격 host에서 local/test stack과 공존하도록 host publish 포트와 compose project/network를 분리한다.**

## 공통 규칙

- dev 테스트/검증은 이 파일을 기준으로 판단한다.
- 사용자가 테스트 환경을 별도로 지정하지 않거나 단순히 `dev`, 테스트 환경, 배포, rollout, runtime 검증이라고 말하면 이 `dev` 환경을 기본 기준으로 삼는다.
- `dev-corp`는 `dev`의 fallback이나 자동 접근 경로가 아니다. 사용자가 `dev-corp` 또는 동등한 회사망/public dev-corp 환경을 명시하지 않은 경우 `agent-test/dev-corp/**`, `iop.ai.kr`, `fe@172.24.63.178`, dev-corp port로 접근하지 않는다.
- 작업 완료 검증은 변경 범위 기준으로 선택한다.
- dev-runtime 배포 범위는 Control Plane, Edge, Node와 이들이 사용하는 공용 package다. `apps/agent/**`와 정확한 package `packages/go/agenttask`는 제외하지만, mac-codex-node가 사용하는 `packages/go/agentprovider/**`와 `packages/go/agentruntime`은 포함한다. 제외 범위를 이유로 common orchestration 또는 `dispatch.py`를 수정·삭제하지 않는다.
- 필수 검증을 실행하지 못하면 차단 사유로 보고한다.
- 원격 runtime, smoke, full-cycle, field/bootstrap 같은 배포형 검증은 테스트 시작 시 확정한 배포 기준 ref의 최신 build로 환경 전체를 갱신한 뒤 시작한다. dev-runtime provider pool은 Edge와 macOS/Linux ARM64/Windows AMD64 Node를 모두 같은 source ref에서 rebuild·redeploy·restart하고, compose profile은 검증에 참여하는 Control Plane/Web/Edge image를 같은 source ref에서 rebuild·redeploy·restart한다. 이미 실행 중인 build는 최신으로 추정해 재사용하지 않는다.
- 배포형 검증 전에 source commit과 각 build의 checksum 또는 동등한 build identity가 배포 기준 ref와 일치하는지 확인한다. 하나라도 갱신 또는 일치 확인을 할 수 없으면 과거 build로 테스트하지 말고 차단 사유로 보고한다. 현재 checkout에서 수행하는 source 단위/패키지 테스트와 build 전 테스트는 이 선행조건의 대상이 아니다.
- 새 테스트 환경을 추가하거나 환경 구조를 바꿀 때는 `agent-test/README.md`와 `agent-test/_templates/`의 확장 기준을 따른다.
- 최종 보고에는 실행 명령, 결과, 생략 사유, 남은 위험을 남긴다.
- 환경값, secret, 개인 endpoint는 tracked docs/roadmap에 쓰지 않는다.
- token/secret 원문은 원격 환경에서 주입하고, shell stdout/stderr와 최종 보고에 출력하지 않는다.
- 테스트용 Docker 환경을 작성/수정할 때는 Docker Compose `networks`, IPAM subnet, static IPv4, `extra_hosts`, host publish 문서 어디에도 `192.168.0.0/24` (`192.168.0.X`) 대역을 사용하지 않는다.
- 새 Docker 테스트 subnet이 필요하면 기존 프로젝트 포트/네트워크 표준을 먼저 따르고, 불가피한 경우 host LAN/VPN과 충돌하지 않는 `192.168.0.0/24` 밖의 private subnet만 사용한다.

## 기본 환경

- host: dev runtime evidence는 원격 runner `ssh toki@toki-labs.com`의 `/Users/toki/agent-work/iop-dev` 기준으로 수행한다.
- repo root: 명령은 원격 checkout `/Users/toki/agent-work/iop-dev` 기준으로 실행한다.
- sync 기준: dev 배포의 clean 시작점은 원격 runner에서 `git fetch origin dev main --tags`, `git switch --force-create dev origin/dev`, `git reset --hard origin/dev`, `git clean -fd`를 수행한 상태다. git-flow release를 시작하거나 재개한 뒤에는 그 release HEAD를 배포 기준 ref로 고정하며, 선택된 release ref를 `origin/main`으로 덮어쓰지 않는다. dev runner의 dirty 변경은 보존 대상으로 보지 않는다.
- env file: dev stack은 `docker compose --env-file .env.dev.example ...`로 명시한다.
- compose identity: `COMPOSE_PROJECT_NAME=iop-dev-agent`, `IOP_COMPOSE_NETWORK=iop-dev-agent-net`, `IOP_COMPOSE_SUBNET=10.89.1.0/24`.
- port: web/dev preview `13001`, Control Plane HTTP `18001`, Portal/Control Plane wire test endpoint `19001`, CP-Edge wire `19002`, compose Edge-Node TCP transport `19003`, Postgres host publish `15401`, Redis host publish `16301`, Control Plane metrics `19103`, Prometheus `19111`, Grafana `19121`. dev-runtime provider pool native Edge-Node TCP는 `18084`다.
- operator notice: 기존 테스트 사용자-facing 접속점(`13001`, `18001`, Edge OpenAI-compatible 후보 `18083`)은 변경하지 않는다. 이번 profile 변경은 Control Plane/Edge 관측용 metrics/Prometheus/Grafana 포트 추가로만 공지한다. Grafana/Prometheus는 원격 runner 내부 또는 SSH 터널로 접근한다.
- optional dev field ports: artifact/bootstrap HTTP `18082`, Edge OpenAI-compatible HTTP `18083`, Edge metrics `19101`. 이 값은 compose 기본 stack에 publish되지 않으며 field/bootstrap 또는 Edge direct dev profile이 필요할 때만 사용한다.
- runtime: Go quick check는 local toolchain을 우선한다. Flutter client 포함 검증과 Docker/code-server/full-cycle runtime은 원격 runner를 사용한다.
- remote toolchain: non-login SSH에서는 Homebrew Go와 Flutter PATH가 초기화되지 않을 수 있다. 원격 검증 시작 시 `/opt/homebrew/bin/go`, `/Users/toki/SDK/flutter/bin/flutter`, `/opt/homebrew/bin/protoc`를 확인하고 PATH를 명시한다. newline package 목록을 zsh 변수로 넘기거나 package-parallel test를 사용하지 말고 package별 순차 실행을 기본으로 한다.
- package manager: Go modules / Makefile / Flutter pub
- docker: 현재 작업 컨테이너에서는 Docker-in-Docker를 사용하지 않는다. Docker compose 검증은 원격 runner 또는 code-server 환경에서 수행한다.
- external service: dev compose Control Plane HTTP `http://toki-labs.com:18001`, dev Client wire `ws://toki-labs.com:19001/client`.
- model endpoint: dev Edge OpenAI-compatible profile을 별도로 띄우는 경우 `http://toki-labs.com:18083/v1`.
- credential: token/secret 원문은 문서에 기록하지 않는다.

## 포트 매핑

| 용도 | local/test | dev |
|---|---:|---:|
| Web preview | `13000` | `13001` |
| Control Plane HTTP | `18000` | `18001` |
| CP Client WS | `19080` | `19001` |
| CP-Edge wire | `19081` | `19002` |
| Compose Edge-Node TCP | `19090` | `19003` |
| Native dev-runtime Edge-Node TCP | 해당 없음 | `18084` |
| Edge artifact/bootstrap | `18080` | `18082` |
| Edge OpenAI-compatible | `18081` | `18083` |
| Edge metrics | `19092` | `19101` |
| Control Plane metrics | `19100` | `19103` |
| Prometheus UI/API | `19110` | `19111` |
| Grafana UI | `19120` | `19121` |
| PostgreSQL host publish | `15400` | `15401` |
| Redis host publish | `16300` | `16301` |

dev-runtime provider pool은 compose Edge-Node TCP `19003`이 아니라 native Edge listen `18084`를 사용한다. 세부 기준은 `agent-test/dev/edge-smoke.md`와 `agent-test/dev/node-smoke.md`를 따른다.

## 런타임 프로필

- local quick check: 현재 checkout에서 Go quick check를 우선 실행한다.
- remote runner: dev runtime evidence, Flutter client, Docker compose, field/bootstrap, 외부 runtime evidence는 `ssh toki@toki-labs.com`의 `/Users/toki/agent-work/iop-dev` 기준으로 수행한다.
- compose dev stack: `.env.dev.example`, `COMPOSE_PROJECT_NAME=iop-dev-agent`, `IOP_COMPOSE_NETWORK=iop-dev-agent-net`, `IOP_COMPOSE_SUBNET=10.89.1.0/24`, Edge-Node TCP `19003`을 사용한다.
- compose observability: Control Plane 관측 그룹은 `postgres`, `redis`, `control-plane`, `web`, `prometheus`, `grafana`만 기본 세팅한다. Edge service는 endpoint 변경 없이 별도 연결 검증이 필요할 때만 붙인다. dev Prometheus는 기존 native Edge metrics `host.docker.internal:19101`을 scrape한다.
- Edge direct dev profile: artifact/bootstrap `18082`, OpenAI-compatible `18083`, metrics `19101`을 필요할 때만 사용한다.
- dev-runtime provider pool: `/Users/toki/agent-work/iop-dev/build/dev-runtime/edge.yaml`과 Edge-Node TCP `toki-labs.com:18084`를 사용한다. 4-node/provider 세부는 `agent-test/dev/edge-smoke.md`와 `agent-test/dev/node-smoke.md`를 따른다.
- external provider field: GX10 vLLM은 `ssh toki@192.168.0.91`, OneXPlayer Lemonade는 현재 작업 호스트에서 `ssh r0bin@192.168.0.59`, RTX5090 Lemonade는 `ssh iop-dev-rtx5090`으로 직접 접속해 확인한다. Windows provider 접속은 원격 runner 경유를 필수 조건으로 보지 않는다.

## 프리플라이트

- plan 작성 시 필수 검증이 현재 checkout을 벗어나 원격 runner, field/bootstrap, 외부 provider, Docker/code-server, emulator/device, 공유 장기 runtime을 사용하면 먼저 테스트 환경 프리플라이트를 계획에 기록한다.
- 테스트 환경 프리플라이트에는 runner, repo root/workdir, branch/HEAD/dirty 상태, local 변경과 원격 source 동기화 여부, binary/artifact 경로와 필요한 help/version 출력, config path, runtime identity, port/process 상태, 외부 host, OS/arch 가정을 포함한다.
- 배포형 검증 프리플라이트는 stale 여부와 관계없이 원격 checkout clean sync, 환경 전체 rebuild·redeploy·restart, source/build identity 확인을 필수 선행 단계로 둔다. 잘못된 identity, missing command, closed port, host OS 불일치, source 미동기화가 확인되면 테스트를 시작하지 않고 setup/sync/rebuild 단계를 수행하거나 blocker로 보고한다. profile 값을 이미 참이라고 가정한 검증 명령만 쓰지 않는다.

## 노드/Provider 인벤토리 위치

- 공통 machine-readable 기준과 환경 routing: `agent-test/inventory.yaml`
- 에이전트 host profile 기준: `agent-test/inventory-agent.yaml`의 `environments.dev.agents`
- dev-runtime provider pool machine-readable 기준: `agent-test/inventory-dev.yaml`
- dev-runtime provider pool과 Edge/OpenAI-compatible 입력 표면 상세 기준: `agent-test/dev/edge-smoke.md`
- dev-runtime Node 접속과 bootstrap 상세 기준: `agent-test/dev/node-smoke.md`
- 공통 provider config 계약 기준: `agent-test/dev/platform-common-smoke.md`
- compose dev stack 기준: `agent-test/dev/control-plane-smoke.md`, `agent-test/dev/client-smoke.md`, `agent-test/dev/testing-smoke.md`

## Field/bootstrap 반복 테스트 기준

- field/bootstrap 검증은 원격 runner의 `/Users/toki/agent-work/iop-dev` checkout과 dev-runtime artifact를 기준으로 수행한다. 세부 Edge/Node profile은 `agent-test/dev/edge-smoke.md`와 `agent-test/dev/node-smoke.md`를 따른다.
- compose dev stack은 Edge-Node TCP `19003`을 사용하고, dev-runtime provider pool은 native Edge listen `18084`를 사용한다. 두 프로필을 섞어서 판정하지 않는다.
- Node bootstrap은 Edge의 `node register`가 출력한 OS별 완성 명령을 그대로 사용한다. 사용자에게 안내하는 명령에는 임의 placeholder, 수동 token 치환, `IOP_*=` named environment parameter를 넣지 않는다.
- token, API key, private credential 원문은 tracked docs, roadmap, 테스트 규칙에 기록하지 않는다. 실행 증거에는 token을 마스킹하거나 명령 생성 사실만 남긴다.
- Linux/macOS Node는 생성된 `curl | bash` 계열 명령을 사용한다. Windows Node는 native PowerShell bootstrap을 기본으로 사용한다.
- dev-runtime 배포는 clean sync 후 `build/dev-runtime/bin/edge`, mac node, Linux/Windows node binary를 같은 source 기준으로 rebuild한다. 배포 후 `edge config refresh --help`, `19093` port, `config refresh --mode dry-run`을 확인한다.
- provider capacity, model/provider mapping은 `config check`와 `config refresh --mode dry-run`을 통과한 뒤 `config refresh --mode apply`로 반영한다. refresh subcommand 또는 `19093` admin port가 없으면 바이너리 rebuild 누락으로 보고 먼저 rebuild한다.
- Edge process restart 또는 일시 단절 후에는 Node reconnect 정책을 검증한다. retry 한계를 넘긴 경우뿐 아니라 Node가 `internal config error` 같은 non-retryable config rejection으로 종료된 경우에도 fixed Edge를 먼저 확인한 뒤 해당 Node를 명시적으로 다시 시작한다.

## 라우팅

- node / smoke / node 실행 파이프라인 baseline: `agent-test/dev/node-smoke.md`
- edge / smoke / edge 실행 그룹과 입력 표면 baseline: `agent-test/dev/edge-smoke.md`
- dev-runtime provider pool, 4-node 연결, GX10 vLLM, OneXPlayer/RTX5090 Lemonade, mac-codex(CLI+MLX provider) node 점검: `agent-test/dev/edge-smoke.md`, `agent-test/dev/node-smoke.md`
- control-plane / smoke / control-plane health와 wire baseline: `agent-test/dev/control-plane-smoke.md`
- client / smoke / Flutter client와 IOP console package baseline: `agent-test/dev/client-smoke.md`
- platform-common / smoke / 공통 설정과 protobuf 계약 baseline: `agent-test/dev/platform-common-smoke.md`
- testing / smoke / 테스트 도구와 full-cycle 검증 baseline: `agent-test/dev/testing-smoke.md`

## 라우팅 규칙

- 여러 항목이 맞으면 모두 읽는다.
- 도메인 매핑이나 domain rule이 있으면 각 도메인의 `<domain>-smoke` 문서를 기본 baseline으로 둔다.
- 도메인이 아직 없을 때만 project-smoke를 fallback baseline으로 둔다.
- 도메인/검증 시나리오별 문서는 다른 테스트 문서로 라우팅하지 않는다.
