iop/agent-test/dev/edge-smoke.md
toki 2f560e3f3b feat: provider pool admission, policy config, snapshot source task archive + runtime updates
- Archive completed subtask plans/code reviews (04, 05+03,04, 07+03)
- Add provider_pool_admission_test.go
- Update edge config types, load, catalog validation
- Update runtime, config refresh, service layers for admission
- Update test docs and inventory
- Update provider scheduling, resolution, tunnel, status modules
2026-07-19 22:41:05 +09:00

14 KiB

test_env test_profile domain verification_type last_rule_updated_at
dev edge-smoke edge smoke 2026-07-19

edge-smoke dev 테스트

읽기 조건

  • apps/edge/** 변경 또는 edge registry, transport, service, console, OpenAI-compatible/A2A 입력 표면 dev 검증 판단이 필요한 경우

적용 범위

  • apps/edge/cmd/edge/**
  • apps/edge/internal/bootstrap/**
  • apps/edge/internal/transport/**
  • apps/edge/internal/service/**
  • apps/edge/internal/events/**
  • apps/edge/internal/input/**
  • apps/edge/internal/openai/**
  • apps/edge/internal/opsconsole/**
  • apps/edge/internal/node/**

분류

  • domain: edge
  • verification_type: smoke
  • scope: edge 실행 그룹, node registry, input surface baseline

환경

  • host: local checkout. dev runtime, external CLI, shared port evidence가 필요하면 원격 runner를 사용한다.
  • port: compose Edge-Node TCP transport 19003; dev artifact/bootstrap HTTP 후보 18082, dev Edge OpenAI-compatible HTTP 후보 18083, dev Edge metrics 후보 19101.
  • runtime: Go 1.24
  • package manager: Go modules / Makefile
  • docker: unit/smoke quick check는 Docker를 요구하지 않는다. compose dev 검증은 docker compose --env-file .env.dev.example ...로 수행한다.
  • external service: dev artifact/base URL 후보 http://toki-labs.com:18082, dev Edge runtime 주소 후보 toki-labs.com:19003
  • model endpoint: dev OpenAI-compatible base URL 후보 http://toki-labs.com:18083/v1
  • credential: token/secret 원문은 문서에 기록하지 않는다.

dev-runtime provider pool 인벤토리

dev-runtime provider pool과 4-node 연결 상태를 점검할 때는 agent-test/dev/inventory.yaml의 machine-readable 값을 우선하고, 원격 runner ssh toki@toki-labs.com/Users/toki/agent-work/iop-dev checkout을 기준으로 한다.

  • Edge config: build/dev-runtime/edge.yaml
  • Edge id: edge-toki-labs-dev
  • Control Plane HTTP: http://127.0.0.1:18001
  • bootstrap HTTP: http://toki-labs.com:18082
  • Edge OpenAI-compatible base URL: http://toki-labs.com:18083/v1
  • Edge-Node TCP transport: toki-labs.com:18084
  • active model alias: ornith:35b
  • Qwen model alias: qwen3.6:35b는 현재 mac-mlx-vllm에만 남아 있다. gx10-vllm, onexplayer-lemonade, rtx5090-lemonade는 Ornith group provider로 대체되었다.
  • host Pi default profile: agent-test/dev/inventory.yamlmodel.pi_agent_profile 기준. 현재 기본 provider/model/thinking level은 iop / ornith:35b / high이며, Pi는 IOP Edge http://toki-labs.com:18083/v1의 Ornith model group을 호출한다. Pi local direct providers는 제거된 상태다.
  • provider/model separation: dev-corp gemma4:26b profile과 stopped DiffusionGemma direct provider는 dev Ornith/Qwen provider-pool 판정 근거로 섞지 않는다.

노드 후보:

  • mac CLI + MLX provider node: mac-codex-node / mac-codex
    • SSH/user: ssh toki@toki-labs.com
    • 목적: cli adapter, codex app-server + mac-mlx-vllm provider resource
    • workspace: /Users/toki/agent-work/iop-workspace/nomadcode
    • MLX vLLM provider: mac-mlx-vllm
      • provider endpoint: http://127.0.0.1:8002/v1
      • served model: mlx-community/Qwen3.6-35B-A3B-4bit
      • capacity baseline: 2
      • priority baseline: 2
      • workdir: /Users/toki/agent-work/iop-mlx-vllm
      • runtime baseline: vllm-mlx, --max-num-seqs 2, --max-kv-size 262144, --max-request-tokens 262144, --use-paged-cache --paged-cache-block-size 64 --max-cache-blocks 4096, --enable-auto-tool-choice --tool-call-parser qwen --reasoning-parser qwen3, --default-chat-template-kwargs {"enable_thinking": true}
      • KV policy: per-call window bound 262144, one full context-size setting
      • long-context admission baseline: total_context_tokens=262144, long_context_capacity=1 (KV budget 262144 fits one full 262144-window request; long slot count is not the normal capacity 2)
  • GX10 vLLM node: gx10-vllm-node / gx10-vllm
    • SSH/user: ssh toki@192.168.0.91
    • provider endpoint: http://192.168.0.91:8001/v1
    • served model: ornith:35b
    • capacity baseline: 4
    • priority baseline: 1
    • runtime baseline: vllm, model deepreinforce-ai/Ornith-1.0-35B-FP8, --served-model-name ornith:35b, --dtype bfloat16, --max-model-len 262144, --max-num-seqs 4, --gpu-memory-utilization 0.50, --enable-prefix-caching, --enable-auto-tool-choice --tool-call-parser qwen3_xml, --reasoning-parser qwen3, --trust-remote-code, --language-model-only
    • long-context admission baseline: total_context_tokens=1048576, long_context_capacity=4 (vLLM log: GPU KV cache 1060912 tokens, max concurrency 4.05x for 262144-token requests)
    • workspace: /home/toki/iop-gx10-vllm
  • OneXPlayer Lemonade node: onexplayer-lemonade-node / onexplayer-lemonade
    • SSH/user: ssh r0bin@192.168.0.59
    • 접속 기준: 현재 작업 호스트에서 직접 SSH
    • provider endpoint: http://192.168.0.59:13305/v1
    • served model: Ornith-1.0-35B-GGUF-llamacpp-tp1-Q5_K_M
    • capacity baseline: 3
    • priority baseline: 2
    • load baseline: checkpoint LordNeel/Ornith-1.0-35B-GGUF-llamacpp-tp1:Q5_K_M, backend vulkan, ctx size 524288, llamacpp_args="--spec-type none -cb -fa on -b 4096 -ub 1024 --kv-unified", save_options=true
    • long-context admission baseline: total_context_tokens=524288, long_context_capacity=2 (-np 고정 분할을 제거하고 --kv-unified를 사용한다. /slots는 auto slots 4개와 slot n_ctx=262144를 보고한다)
    • workspace: C:/Users/r0bin/iop-field
  • RTX5090 Lemonade node: rtx5090-lemonade-node / rtx5090-lemonade
    • SSH/user: ssh iop-dev-rtx5090
    • 접속 기준: 현재 작업 호스트의 local SSH config alias와 public-key batch 인증
    • provider endpoint: http://192.168.0.111:13305/v1
    • served model: Ornith-1.0-35B-GGUF-llamacpp-tp1-Q5_K_M
    • capacity baseline: 1
    • priority baseline: 0
    • load baseline: backend cuda, Q5 GGUF, Q8 KV, ctx size 262144, Lemonade host=0.0.0.0
    • long-context admission baseline: total_context_tokens=262144, long_context_capacity=1
    • process baseline: Windows 예약 작업 IOP Dev Node RTX5090 Lemonade
    • workspace: C:/Users/r0bin/iop-field

OneXPlayer와 RTX5090 Lemonade는 현재 Ornith Q5 GGUF를 사용하고 runtime speculative decoding은 --spec-type none으로 끈다. Qwen을 다시 올릴 때도 fixed -np 3 분할은 쓰지 말고 현재 검증된 --kv-unified 방식으로 resource를 공유한다.

OneXPlayer Lemonade Node는 원격 runner나 Edge host에서 다시 SSH하거나 proxy process로 띄우지 않는다. 현재 작업 호스트에서 OneXPlayer Windows host에 ssh r0bin@192.168.0.59로 직접 접속한 뒤 generated PowerShell bootstrap을 실행한다.

RTX5090 Lemonade Node도 원격 runner나 Edge host를 경유하지 않는다. 현재 작업 호스트에서 ssh iop-dev-rtx5090으로 public-key batch 접속하고 예약 작업으로 Node를 관리한다. Lemonade가 localhost-only로 bind되면 Node 연결이 실패하므로 0.0.0.0:13305 listener를 확인한다.

mac-mlx-vllm provider는 mac-codex-node 소속 resource로, Edge host와 같은 macOS host에서 vllm-mlx process로 실행한다. vllm-mlx API는 외부에 직접 노출하지 않고 127.0.0.1:8002에 bind하며, Edge OpenAI-compatible adapter가 local bearer header로 호출한다. 운영 파일은 /Users/toki/agent-work/iop-mlx-vllm/vllm-mlx.pid, logs/vllm-mlx.stdout.log, logs/vllm-mlx.stderr.log를 기준으로 한다. Docker와 macOS 여유 메모리를 고려해 capacity는 2를 기본선으로 유지한다.

명령

  • setup:
  • lint:
  • unit: go test ./apps/edge/...
  • smoke: ./scripts/e2e-smoke.sh는 기본 포트 임시 설정을 쓰는 보조 smoke이므로 dev 포트 override 필요 여부를 먼저 확인한다.
  • e2e: make test-e2e는 보조 smoke이며 full-cycle 실제 구동을 대체하지 않는다.
  • model: dev OpenAI-compatible profile을 띄운 경우 iop-edge smoke openai --base-url http://127.0.0.1:18083
  • full-cycle: repo 내부 edge-node 진단, iop-edge smoke openai, OpenAI-compatible 입력 표면 수동 검증

필수 검증

  • 변경한 edge 패키지 또는 go test ./apps/edge/...를 실행한다.
  • registry, service, transport, console, HTTP/A2A 입력 표면을 바꾼 경우 edge-node 메시지 2회 왕복과 command 응답을 확인한다.
  • OpenAI-compatible 경계를 바꾼 경우 dev 18083 기준 iop-edge smoke openai 또는 동등한 /healthz, /v1/models, /v1/responses 확인으로 edge service와 node adapter 경로 수렴을 확인한다.
  • OpenAI-compatible tool-call 경계(apps/edge/internal/openai/**의 text tool-call 합성/validation)를 바꾼 경우 dev 18083 /v1/chat/completions에 Pi/Cline형 tools[] 요청을 non-stream/stream 각각 최소 1회 보내 raw text tool-call boundary smoke를 수행한다. token은 원격 환경 변수에서 주입하고 원문을 명령/로그/보고에 남기지 않는다.
  • dev provider-pool tool-call drift를 확인할 때는 active model group별 provider만 섞는다. Ornith group은 gx10-vllm, onexplayer-lemonade, rtx5090-lemonade direct endpoint에 동일한 tools[] + tool_choice:"auto" Chat Completions 요청을 보내 200과 tool_calls 구조를 확인한 뒤, Edge 18083 model ornith:35b에도 동시 요청을 보낸다. Qwen group 검증은 mac-mlx-vllm 단독 기준으로 별도 수행한다.
  • bootstrap/artifact 경계를 바꾼 경우 dev artifact/base URL 후보 18082가 local/test 18080 field baseline을 덮어쓰지 않는지 확인한다.

보조 검증

  • ./scripts/e2e-smoke.sh는 edge-node 최소 생존 확인에 사용한다.
  • ./scripts/e2e-openai-ollama.sh는 OpenAI-compatible Ollama 입력 표면 보조 확인에 사용한다.

판정 기준

  • node 등록, /nodes, console 메시지 전송, 기대 payload를 포함한 [node-*-message] 출력, 같은 run의 complete event가 확인된다.
  • node 로컬 [node-message] payload 라인 목록과 edge [node-*-message] payload 라인 목록이 run별로 내용/순서까지 동일해야 한다.
  • edge complete는 같은 run의 마지막 [node-*-message] 이후에만 정상이다.
  • OpenAI-compatible smoke에서 /healthz, /v1/models, /v1/responses가 기대 상태로 응답한다.
  • raw text tool-call boundary smoke: Pi/Cline형 tools[] 요청에서 응답 body와 SSE delta 어디에도 <tool_call>, {{, <|mask_end|> 원문이 성공 content로 남지 않는다. 요청 tools[]에 있는 valid raw text tool-call은 message.tool_calls(또는 stream delta.tool_calls)와 finish_reason: "tool_calls"로 정규화되고, unknown tool hallucination이나 malformed 블록은 성공 content가 아니라 non-stream tool_validation_error(HTTP 502) 또는 SSE tool_validation_error 이벤트로 끝난다. non-stream/strict buffered stream은 bounded retry 후 차단을 확인한다. 세부 payload와 계약은 docs/edge-local-dev-guide.md의 Raw text tool-call boundary smoke와 agent-contract/outer/openai-compatible-api.md를 따른다.
  • raw boundary smoke evidence는 tracked 문서가 아니라 ignored run 위치(agent-test/runs/**)나 code-review output path에 저장하고, 저장물에도 token 원문을 남기지 않는다.
  • provider-pool dispatch는 in_flight >= capacity인 provider를 후보에서 제외하고, 남은 후보 중 가장 낮은 in_flight 레벨을 먼저 선택한다. 같은 in_flight 레벨 안에서는 낮은 priority 값과 rotation으로 분산한다.
  • dev-runtime Ornith capacity smoke는 /v1/responses/v1/chat/completions 각각에 Ornith provider capacity 총합 + 1개 동시 요청을 보낸다. 현재 Ornith group은 gx10-vllm=4, onexplayer-lemonade=3, rtx5090-lemonade=1이므로 9개 동시 요청에서 총 in_flight=8, queued>=1, mac-mlx-vllm=0 관측을 기준으로 한다. ornith:35bornith-fast는 provider-owned shared capacity 구현 전까지 model group별 capacity를 독립 집계하므로 이 smoke에서는 한 alias만 사용한다.
  • capacity smoke 완료 후 대상 provider의 in_flight=0, queued=0 회복을 확인한다.
  • long-context admission 시나리오(normal 10-way, mixed long/normal, all-long-slot-full)와 최종 회복 근거는 agent-test/dev/long-context-admission-smoke.mdscripts/e2e-long-context-admission-smoke.sh를 사용한다.
  • 2026-06-24 dev 13-way 확장 smoke는 Mac capacity가 3이던 이전 관측이다. 해당 run에서는 /v1/chat/completions 13개 요청 성공, peak in_flight=10, 실제 queue 대기 3개, 최종 회복 in_flight=0, queued=0이 관측되었다. 현재 Mac capacity 2 기준 13-way 확장 smoke 기대치는 peak in_flight=9, queue 대기 4개 이상이다.
  • Qwen provider-pool smoke는 thinking/reasoning 텍스트가 포함될 수 있다. 추론 출력 자체를 실패로 보지 말고 HTTP 성공, model alias, final marker 포함 여부, provider node log/run count 증가로 판정한다. 응답 전체가 특정 token과 정확히 같은지 비교하는 strict exact-match는 이 profile의 기본 판정으로 쓰지 않는다.
  • Qwen provider를 agent/tool-call 용도로 검증할 때는 일반 chat smoke와 별도로 forced tool call, auto tool call, streaming delta.tool_calls, multi-turn tool result 후 최종 답변을 확인한다. raw native marker나 reasoning text가 assistant content로 새면 해당 model/runtime의 parser/template profile 미확정으로 보고한다.
  • Qwen runtime에는 Qwen 전용 parser/template 검증값만 사용한다. dev-corp Gemma 계열의 tool_call_parser=gemma4, reasoning_parser=gemma4, Gemma4 chat template/profile을 Qwen provider에 복사하지 않는다.
  • bootstrap 사용자 명령은 완성된 URL과 positional token 하나만 포함한다.

기준 출력 예시

edge> /nodes
[edge] sent run_id=...
[node-*-message] IOP_EXPECTED_REPLY
[node-*-event] complete

차단 기준

  • dev host 또는 Edge-Node TCP port 접근이 불가능하다.
  • 외부 CLI profile 검증에 필요한 CLI 설치, 계정, provider 상태가 없다.
  • dev artifact/model/metrics 포트가 기존 field baseline과 충돌한다.

보고 항목

  • 실행한 명령:
  • 성공한 검증:
  • 실패/차단된 검증:
  • 생략 사유:
  • 남은 위험:

금지 사항

  • secret, token, 개인 endpoint 원문은 tracked 파일에 기록하지 않는다.
  • field baseline 포트(18080, 18081, 19090, 19092)를 dev 전용 포트로 재사용하지 않는다.