diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index 9a0223a..6c537f8 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -24,7 +24,7 @@ - `proto/iop/` — IOP 메시지 계약 원본이다. - `proto/gen/iop/` — protobuf 생성물이다. - `configs/` — 앱별 YAML 설정 예시이다. -- `bin/` — 사용자가 직접 실행하는 edge/node/web shell entrypoint와 field binary build entrypoint이다. +- `bin/` — 개발 보조 shell entrypoint와 field binary build entrypoint이다. Edge/Node 운영 UX의 공식 표면은 `iop-edge`/`iop-node` 바이너리 command로 모은다. - `scripts/` — 보조 E2E smoke와 입력 표면 검증 스크립트이다. - `Makefile` — 빌드와 테스트 진입점을 정의한다. - `docs/` — 아키텍처 및 운영 방향 문서이다. field 테스트 환경, 외부 테스트 포트, one-line bootstrap 기준은 `docs/deploy-dev.md`를 우선 진입점으로 본다. @@ -48,12 +48,16 @@ - 새 node 어댑터는 `runtime.Adapter`를 구현하고 `apps/node/internal/bootstrap/module.go`에서 registry에 등록한다. - 내부 실행 요청과 상태 저장에서는 `adapter`, `target`, `execution` 용어를 우선한다. `model`은 외부 API 호환이나 legacy placeholder일 때만 허용한다. - Control Plane은 Node를 직접 연결/스케줄링하지 않고 Edge를 통해 시스템을 제어한다. Edge는 자신의 로컬 런타임 상태와 Node registry를 소유한다. +- 사용자 실행, 로컬/dev 배포, field 테스트, 임시 Control Plane 대체 흐름은 사용법을 `bin/`, `scripts/`, 별도 dev deploy 바이너리, 모델용 skill로 흩뜨리지 않고 `iop-edge`와 `iop-node` command 표면에 모은다. helper script가 필요해도 공식 사용자 경로가 되면 안 된다. +- Control Plane이 없는 테스트/개발 배포 단계에서는 `edge.yaml`을 테스트용 Control Plane source of truth로 본다. Node별 id/alias/token/adapter/runtime 설정은 Edge config의 `nodes[]`에서 관리한다. +- Node 사용자 UX는 bootstrap 명령 하나로 끝나야 한다. 사용자가 `node.yaml`을 만들거나 편집하거나 `iop-node serve --config ...`를 직접 실행하는 흐름을 기본 경로로 두지 않는다. bootstrap 내부에서 임시 상태나 설정 파일을 만들 수 있더라도 이는 구현 세부이며 사용자 가이드와 기본 운영 UX에 노출하지 않는다. +- 바이너리 배포 UX는 repo checkout 위치에 묶이지 않아야 한다. `iop-edge`/`iop-node`는 아무 작업 디렉터리에서 실행 가능해야 하며, 로컬/dev bundle에서는 Edge 설정을 바이너리와 같은 디렉터리의 `edge.yaml` 같은 구조화된 config에 모으는 방향을 우선한다. Node 쪽은 별도 사용자 config 파일이 아니라 Edge가 제공하는 bootstrap으로 연결한다. - Edge-Node 내부 통신은 TCP 기반 protobuf 메시지 흐름을 우선한다. Portal-Control Plane처럼 브라우저/앱 표면이 필요한 경계는 proto-socket WebSocket/WSS를 사용할 수 있다. gRPC 도입, Edge-Node 기본 transport의 WebSocket 전환, actor/FSM/plugin framework 도입은 금지한다. - protobuf 계약 변경 시 `proto/iop/*.proto`를 먼저 수정하고 `make proto`로 `proto/gen/iop/*.pb.go`를 갱신한다. 생성 파일은 직접 수정하지 않는다. - 앱 설정 구조 변경 시 `packages/config`의 struct/default와 `configs/*.yaml` 예시를 함께 확인한다. - 테스트는 변경 범위에 맞춰 `go test ./...` 또는 대상 패키지 테스트를 실행한다. - 사용자 실행 파이프라인에 닿는 작업을 한 경우, 작업 완료 후 `agent-ops/rules/project/domain/testing/rules.md`의 검증 기준을 따른다. -- field 테스트 환경 또는 one-line bootstrap 작업은 `docs/deploy-dev.md`의 Field 테스트 환경 라우팅과 활성 Milestone `Field Bootstrap UX와 테스트 포트 정비`를 먼저 확인한다. +- field 테스트 환경 또는 one-line bootstrap 작업은 `docs/deploy-dev.md`의 Field 테스트 환경 라우팅과 `docs/field-bootstrap-work-guide.md`를 먼저 확인한다. - Node, OTO, specialized agent, Control Plane enrollment 등 사용자가 대상 host에서 실행하는 bootstrap/install command 작업은 `agent-ops/rules/project/domain/testing/rules.md`의 one-line bootstrap UX 기준을 따른다. - code-server 기반 field 테스트 포트는 원격 `ssh toki@toki-labs.com`의 `~/docker/services/code-server/compose/docker-compose.yml`에서 관리한다. 기준 host port는 web/dev `13000-13099`, artifact/bootstrap HTTP `18080`, OpenAI-compatible HTTP `18081`, Edge-Node transport `19090`, Edge metrics `19092`, OTO/specialized agent transport `19190`이다. - 상세 DB schema, event schema, permission/policy/audit model, federation, mTLS 구현 세부, Portal UI 세부 기획은 각 작업에서 별도로 결정한다. @@ -86,6 +90,6 @@ ## 스킬 라우팅 - 사용자 실행 파이프라인 검증, bin shell 사용자 흐름, 메시지 2회 왕복, edge command 응답, 보조 E2E smoke, full-cycle 실제 구동, `bin/edge.sh`/`bin/node.sh` 통합 테스트: `agent-ops/skills/project/e2e-smoke/SKILL.md` -- field 테스트 포트, artifact/bootstrap HTTP, one-line Node bootstrap, code-server compose 기반 외부 테스트 환경: `docs/deploy-dev.md`와 활성 Milestone `agent-roadmap/phase/serving-routing-optimization/milestones/field-bootstrap-test-port-readiness.md` +- field 테스트 포트, artifact/bootstrap HTTP, one-line Node bootstrap, code-server compose 기반 외부 테스트 환경: `docs/deploy-dev.md`와 `docs/field-bootstrap-work-guide.md` - bootstrap/install UX, Agent Bootstrap, OTO 등록, Control Plane enrollment처럼 사용자가 대상 host에서 복사해 실행하는 명령을 설계하거나 바꿀 때: `agent-ops/rules/project/domain/testing/rules.md`의 one-line bootstrap UX 기준과 `docs/deploy-dev.md`의 field bootstrap 기준을 확인한다. - 반복 작업이 확인되면 `agent-ops/skills/project//SKILL.md`를 생성하고 이 표에 등록한다. diff --git a/docs/deploy-dev.md b/docs/deploy-dev.md index b56e27f..b3613b3 100644 --- a/docs/deploy-dev.md +++ b/docs/deploy-dev.md @@ -18,7 +18,7 @@ edge host node host iop-node binary - node.yaml + bootstrap-managed runtime state oto build host oto binary @@ -105,11 +105,8 @@ dev 초기 단계에서는 repo의 `configs/edge.yaml`을 기준으로 포트와 ## Node 실행 -Jenkins 산출물의 `iop-node`를 node host에 배포한 뒤, 초기에는 edge 주소와 token이 들어 있는 `node.yaml`로 직접 실행한다. - -```bash -./iop-node serve --config /etc/iop/node.yaml -``` +사용자/field 기본 경로에서 Node는 직접 설정 파일을 만들거나 `iop-node serve --config ...`로 실행하지 않는다. +Edge가 제시한 bootstrap 명령을 대상 host에서 실행하면 다운로드, 검증, 연결, 실행까지 이어져야 한다. repo root에서 수동으로 검증할 때는 기존 helper를 사용할 수 있다. @@ -139,7 +136,8 @@ field bootstrap UX는 Jenkins agent 연결처럼 Edge가 command를 제시하고 - Edge 또는 field artifact server가 `dist/field//-/iop-node`를 정해진 URL로 노출한다. - Apple Silicon Mac은 `darwin/arm64` 산출물을 사용한다. `linux/arm64`는 Mac 실행 대상이 아니다. -- 사용자가 실행하는 명령은 한 줄 수준으로 유지하고, 내부에서 다운로드, 실행 권한 부여, config 생성, `iop-node serve`까지 이어진다. +- 사용자가 실행하는 명령은 한 줄 수준으로 유지하고, 내부에서 다운로드, 실행 권한 부여, 필요한 내부 상태 준비, `iop-node` 실행까지 이어진다. +- 사용자가 `node.yaml`을 만들거나 확인하거나 편집하는 흐름은 기본 경로에 두지 않는다. - 직접 포트가 아직 적용되지 않았거나 외부망에서 막히면 SSH tunnel 또는 reverse tunnel은 fallback으로만 사용한다. Apple Silicon Node용 field artifact는 다음처럼 만든다. Node token은 artifact에 굽지 않고 사용자 명령의 첫 번째 인자로 전달한다. @@ -179,7 +177,8 @@ python3 -m http.server 18080 --bind 0.0.0.0 -d dist/field/ curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash -s CHANGE_ME_FIELD_TOKEN ``` -bootstrap 스크립트는 `~/iop-field`를 만들고, `darwin-arm64/iop-node`와 `SHA256SUMS`를 받아 checksum을 확인한 뒤 `node.yaml`을 생성하고 `iop-node serve --config ./node.yaml`을 실행한다. +bootstrap 스크립트는 `~/iop-field`를 만들고, `darwin-arm64/iop-node`와 `SHA256SUMS`를 받아 checksum을 확인한 뒤 필요한 내부 상태를 준비하고 `iop-node`를 실행한다. +내부 구현이 임시 설정 파일을 쓰더라도 사용자에게 그 파일을 만들거나 관리하게 하지 않는다. 첫 번째 인자 `CHANGE_ME_FIELD_TOKEN`은 Edge config의 `nodes[].token`과 같은 값이어야 한다. ## Field Bootstrap 작업자 테스트 Runbook @@ -338,7 +337,6 @@ curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash -s C ```text ~/iop-field/iop-node -~/iop-field/node.yaml ``` Edge 로그에는 `node registered`와 `node-silicon-ollama`가 보여야 한다. @@ -369,7 +367,7 @@ curl -fsS -N http://127.0.0.1:8080/v1/chat/completions \ 성공 기준: -- Mac의 bootstrap 명령이 `iop-node serve --config `까지 도달한다. +- Mac의 bootstrap 명령이 foreground Node process 실행까지 도달한다. - Edge 로그에 `node registered`가 나온다. - `/v1/models`가 `gemma4:26b`를 포함한다. - non-streaming 응답에서 content가 비어 있지 않다. @@ -388,7 +386,6 @@ Node가 Edge에 연결하지 못함: ```bash nc -vz toki-labs.com 19090 -cat ~/iop-field/node.yaml ``` token 불일치: @@ -406,11 +403,7 @@ Apple Silicon Mac에서 Node와 Ollama를 함께 실행하는 경우 Edge config ### 9. 정리 Mac의 foreground Node process는 `Ctrl-C`로 종료한다. -재실행은 같은 one-line command를 다시 실행하거나, 이미 받은 binary를 직접 실행한다. - -```bash -~/iop-field/iop-node serve --config ~/iop-field/node.yaml -``` +재실행은 같은 one-line bootstrap command를 다시 실행한다. 관련 완료 Milestone 기록은 `agent-roadmap/archive/phase/serving-routing-optimization/milestones/field-bootstrap-test-port-readiness.md`에 보존되어 있다. 이후 field bootstrap 관련 구현, 문서, 테스트 포트 변경은 새 활성 Milestone 또는 후속 Phase 범위로 판단한다. @@ -543,7 +536,7 @@ Agent 설치가 어렵거나 임시 제어만 필요한 대상의 remote termina 1. `docker compose ps`에서 `postgres`, `redis`, `control-plane`, `web`이 healthy/running인지 확인한다. 2. edge host에서 `iop-edge console --config /etc/iop/edge.yaml`을 실행한다. -3. node host에서 `iop-node serve --config /etc/iop/node.yaml`을 실행한다. +3. node host에서 Edge가 제시한 bootstrap 명령을 실행한다. 4. edge console에서 `/nodes`로 node 등록을 확인한다. 5. 메시지 2회를 보내고 각 요청의 start, message, complete event가 edge console에 표시되는지 확인한다. 6. `/capabilities`, `/transport`, `/sessions`를 실행해 command 응답을 확인한다. @@ -598,7 +591,8 @@ iop-edge version ## Node setup CLI -Node 바이너리는 호스트 환경 준비를 `setup` 명령으로 일원화한다. 공식 운영 경로는 하나다. +Node setup CLI는 현재 구현된 host setup 보조 기능이다. field 사용자 기본 경로는 Node setup/config가 아니라 Edge가 제시한 bootstrap 명령이다. +Control Plane 없는 개발 단계에서도 Node별 실행 설정은 Edge config의 `nodes[]`에서 관리한다. ```bash sudo iop-node setup --enable --start @@ -619,7 +613,7 @@ sudo iop-node setup --dry-run --binary /usr/local/bin/iop-node - `systemctl daemon-reload` - 옵션에 따른 `--enable`, `--start`, `--restart` -`setup`의 `--config` 기본값은 `/etc/iop/node.yaml`이다. dev 단계 명령(`serve`, `config print/check`)의 root persistent `--config` 기본값(`configs/node.yaml`)과는 다르다. +현재 구현상 `setup`의 `--config` 기본값은 `/etc/iop/node.yaml`이고, dev 단계 명령(`serve`, `config print/check`)의 root persistent `--config` 기본값은 `configs/node.yaml`이다. 이 경로는 구현 현황 설명이며 사용자-facing field bootstrap 계약으로 보지 않는다. 별도 `render`, `service install`, `service status` 명령은 초기 범위에 넣지 않는다. 검토와 CI 확인은 `setup --dry-run`으로 흡수하고, 상태/로그/재시작은 `systemctl`과 `journalctl`을 기준 운영 도구로 둔다. diff --git a/docs/field-bootstrap-user-test.md b/docs/field-bootstrap-user-test.md index 443ec90..5cbbf6a 100644 --- a/docs/field-bootstrap-user-test.md +++ b/docs/field-bootstrap-user-test.md @@ -30,7 +30,6 @@ curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash -s < ```bash ollama list | grep 'gemma4:26b' -cat ~/iop-field/node.yaml ``` 그리고 Node 연결 명령을 실행한 터미널 출력 전체를 함께 보낸다. diff --git a/docs/field-bootstrap-work-guide.md b/docs/field-bootstrap-work-guide.md index d9a033a..f7d38ee 100644 --- a/docs/field-bootstrap-work-guide.md +++ b/docs/field-bootstrap-work-guide.md @@ -8,9 +8,10 @@ - Edge-Node 런타임 연결에 외부 공개가 필요한 포트는 `19090` 하나다. - `18080`은 bootstrap shell script, `iop-node` binary, checksum을 내려받는 artifact HTTP 포트다. Edge-Node 런타임 포트가 아니다. - 현재 field 기준 bootstrap/artifact 외부 주소는 `http://toki-labs.com:18080`이다. -- 생성되는 `node.yaml`의 `transport.edge_addr`만 외부 접속 주소인 `toki-labs.com:19090`으로 맞춘다. +- bootstrap이 사용하는 Edge runtime 주소는 `toki-labs.com:19090`으로 맞춘다. - Cline/OpenAI-compatible 외부 주소는 `http://toki-labs.com:18081/v1`이다. - 사용자에게 보이는 bootstrap 명령은 완성된 URL과 token positional value 하나만 포함한다. `IOP_*=` named parameter를 사용자 기본 경로에 두지 않는다. +- 사용자에게 `node.yaml` 생성, 확인, 편집, `iop-node serve --config ...` 실행을 요구하지 않는다. bootstrap 내부 상태 파일은 구현 세부로만 취급한다. ## 완료 테스트 스냅샷