Ornith provider pool의 현재 구성과 동시성 검증 근거를 일치시키고, stream gate 운영 모드와 관련 작업 규칙을 함께 추적하기 위해 반영한다.
29 KiB
| name | description |
|---|---|
| dev-runtime-deploy | dev 배포, dev-runtime 배포, Edge/Node dev 환경 배포 요청에서 dev commit count 기반 git-flow release를 만들고 clean sync, 전체 테스트, rebuild, 원격 배포, OpenAI-compatible capacity smoke, release finish와 tag push를 수행하는 절차 |
dev-runtime-deploy
목적
dev-runtime provider pool을 dev 기준 git-flow release로 배포한다. dev commit count로 release version을 만들고 release branch에서 전체 테스트, rebuild, Edge/Node 재시작, provider snapshot 기반 capacity 검증을 완료한 뒤에만 release를 finish하고 tag를 원격에 반영한다.
언제 호출할지
- 사용자가
dev 배포,dev-runtime 배포,배포해봐처럼 dev 환경 배포를 요청할 때 - Edge, mac-codex-node(CLI adapter + mac-mlx-vllm provider resource), GX10 vLLM node, OneXPlayer Lemonade node, RTX5090 Lemonade node로 이루어진 dev-runtime provider pool을 갱신할 때
- OpenAI-compatible
/v1/responses또는/v1/chat/completions경로가 provider capacity만큼 채워지는지 검증할 때 - dev 환경의 remote runner, node 접속 정보, provider capacity, model alias 변경을 배포 절차에 반영할 때
입력
env: 배포 대상 환경. 기본값은dev이다.model: OpenAI-compatible model alias. 지정하지 않으면 dev 환경 문서의 기준 model을 사용한다.capacity_targets: provider별 기대 capacity. 지정하지 않으면 dev 환경 인벤토리 또는agent-test/dev/*문서에서 읽는다.- 배포 기준 branch는 항상
dev이며 다른source_ref로 대체하지 않는다. - dev-runtime 배포 범위에서
apps/agent/**와 정확한 packagepackages/go/agenttask는 제외한다.packages/go/agentprovider/**,packages/go/agentruntime,packages/go/credentiallease는 Edge/mac Node가 사용하므로 제외하지 않는다.
Git Flow release 규칙
- develop branch는
dev, production branch는main을 사용한다. - release version은 clean sync된
origin/devHEAD에서git rev-list --count HEAD로 계산한dev-<commit-count>이다. - release branch는 git-flow 기본 prefix를 적용한
release/dev-<commit-count>, tag는dev-<commit-count>를 사용한다. - 별도 버전 파일은 만들지 않는다. release branch와 최종 tag가 배포 버전 기록이다.
- release branch에서 빌드와 배포를 수행하고 모든 필수 테스트와 live capacity smoke가 성공한 경우에만
git flow release finish를 실행한다. - finish는 local production/develop merge와 tag 생성을 수행하고, 검증된
main,dev, tag, release branch 삭제를 atomic push로 원격에 함께 반영한다. - 검증 실패 시 finish, tag 생성,
main/dev반영을 수행하지 않고 release branch를 유지한다. - 같은 version의 게시된 release branch가 있고 tag가 없으면 새 branch를 만들지 않고 해당 release를 재개한다.
먼저 확인할 것
agent-ops/rules/project/domain/testing/rules.md를 읽고 사용자 실행 파이프라인 검증 기준을 확인한다.go build -o /tmp/iop-inventory-query ./scripts/inventory-query로 current checkout query binary를 만든다./tmp/iop-inventory-query --env dev로 env projection을 먼저 확인한다.- 필요한 selector별 bounded 조회는 아래 명령으로 실행한다:
- node:
/tmp/iop-inventory-query --env dev --node <node-id-or-alias> - provider:
/tmp/iop-inventory-query --env dev --provider <provider-id> - model:
/tmp/iop-inventory-query --env dev --model <model-alias>
- node:
- 직접 실행 exit 2가 schema/file 오류일 때만 canonical inventory 전체 읽기로 fallback하고, exit 1은 zero-match로 보고한다.
- dev-runtime provider pool과 compose/local profile을 섞지 않는다. dev-runtime은 native Edge/Node runtime과 dev-runtime config를 기준으로 한다.
- 원격 runner의 non-login SSH는 Go/Flutter 경로가 비어 있을 수 있다. 실행 전에
PATH=/opt/homebrew/bin:/Users/toki/SDK/flutter/bin:/Users/toki/go/bin:/Users/toki/.pub-cache/bin:$PATH를 설정하거나/bin/zsh -lc로 toolchain 경로를 확인한다. - provider runtime option은
agent-test/inventory-dev.yaml의 model family별 값을 우선한다. 현재 Qwen은 mac-mlx-vllm의tool_call_parser=qwen,reasoning_parser=qwen3,default_chat_template_kwargs.enable_thinking=true를 사용한다. GX10 Laguna는tool_call_parser=poolside_v1,reasoning_parser=poolside_v1,default_chat_template_kwargs.enable_thinking=true, Pipreserve_thinking=true와 host/home/toki/iop-gx10-vllm/laguna-s-2.1-thinking.jinja의<think>\ngeneration prefix를 사용한다. Gemma/Qwen/Laguna parser와 chat template profile을 서로 복사하지 않는다. - OneXPlayer SSH 접속 정보는 현재 host 기준
ssh r0bin@192.168.0.59이다.toki사용자명 또는 remote runner를 경유한 OneXPlayer 접속을 사용하지 않는다. - RTX5090 SSH는 현재 작업 호스트의 local SSH config alias
ssh iop-dev-rtx5090을 사용한다. 이 alias는 public-key batch 인증을 사용하며, host identity와 공개키 지문은 inventory의rtx5090-lemonade-node.ssh_access에서 확인한다. - 현재 구현의 completion 검증 대상은 legacy
/v1/completions가 아니라/v1/chat/completions이다./v1/completions는 route가 구현되어 있을 때만 별도 검증한다. - 원격 runner에 git-flow가 설치되어 있고
gitflow.branch.master=main,gitflow.branch.develop=dev,gitflow.prefix.release=release/인지 확인한다. - shallow clone이 아니며
origin/dev,origin/main, tag를 fetch할 수 있는지 확인한다. - For a deployment that first merges a feature source into
dev, rungit fetch --prune origin dev main <feature> --tags, thengit remote prune origin, and require the recorded exact feature SHA to match the fetched remote feature SHA. For a regulardevdeployment, rungit fetch --prune origin dev main --tags, thengit remote prune origin. - Use
git ls-remote --heads origin 'refs/heads/release/*'as the authoritative remote release-head check. Treat stale local remote-tracking refs removed by prune as cleanup evidence, not as remote release blockers. origin/main이origin/dev의 ancestor인지 확인한다. 아니면 배포하지 않고 branch 정합화를 먼저 요구한다.- 계산된 tag가 이미 local이나 origin에 있으면 삭제·이동·덮어쓰기하지 않고 완료 상태 또는 partial finish 상태를 보고한다.
- 계산된
release/dev-<count>이외의 release branch가 있으면 중단한다. AVH git-flow는 다른 release가 진행 중이면 새 release start를 허용하지 않는다. - token, secret header, bootstrap token, private key 경로는 최종 보고에 원문으로 출력하지 않는다.
실행 절차
-
환경 인벤토리 확정
- 배포 대상 runner, repo path, Edge id, Control Plane status URL, OpenAI base URL, Edge admin URL, Node SSH 정보를 문서에서 확정한다.
- provider pool 대상 model alias와 provider별 capacity를 확정한다.
- 필수 정보가 없거나 서로 충돌하면 배포를 시작하지 말고 누락/충돌 항목을 보고한다.
-
dev clean sync와 release version 확정
- Run
git fetch --prune origin dev main --tagsin the remote runner checkout, thengit remote prune origin, and clean-sync localdevtoorigin/dev. When the deployment first merges a feature source, fetch the exact feature ref withgit fetch --prune origin dev main <feature> --tagsbefore pruning the remote-tracking namespace. - Determine active remote releases only from the authoritative output of
git ls-remote --heads origin 'refs/heads/release/*'. Record changes to localrefs/remotes/origin/release/*before and after prune only as stale-ref cleanup evidence. - dirty 파일은 보존 대상으로 보지 않는다. 배포 전 clean 상태를 만든다.
- 기본 cleanup은
git clean -fd이다.git clean -fdx는 config, token, secret, runtime artifact까지 삭제할 수 있으므로 사용하지 않는다. - shallow clone이 아닌지,
HEAD와origin/dev가 같은 commit인지,origin/main이origin/dev의 ancestor인지 확인한다. - local
main도origin/main과 같은 commit으로 맞춘다. - sync 후
git status --short --branch,git log --oneline -1,git rev-list --count HEAD를 기록한다. - commit count가
<count>이면 release version을dev-<count>로 확정한다. - 이 시점의
origin/dev를DEV_BASE_SHA,origin/main을MAIN_BASE_SHA로 기록한다.
- Run
-
git-flow release 시작
dev-<count>local/remote tag가 없어야 한다.release/dev-<count>가 local과 origin에 모두 없으면 cleandev에서git flow release start dev-<count>와git flow release publish dev-<count>를 실행한다.- tag 없이 origin의
release/dev-<count>만 있으면git flow release track dev-<count>로 checkout하여 기존 release를 재개한다. local branch도 있으면 local/remote가 같은 commit이고 clean한 경우에만 그대로 재개한다. - 다른 release branch가 있거나 같은 release의 local/remote가 diverge한 상태에서는 자동 삭제·reset하지 않고 중단한다.
- release HEAD는
DEV_BASE_SHA와 같거나 그 descendant여야 한다. - 빌드·배포할 release HEAD를
DEPLOY_SHA, 그 tree를DEPLOY_TREE로 기록한다.
-
빌드 전 전체 테스트
-
clean source 기준으로 Control Plane, Edge, Node와 공용 runtime package를 테스트한다.
apps/agent/**와 정확한 packagepackages/go/agenttask는 dev-runtime 범위에서 제외한다. -
zsh의 newline word splitting이나 package-parallel 실행에 의존하지 않는다. 아래 package 목록을 한 package씩 순차 실행한다.
agentprovider/catalog의 짧은 process probe는 package 병렬 부하에서 timeout이 날 수 있으므로 병렬 실패만으로 source 실패를 단정하지 않고 순차 실행 결과를 기준으로 한다.while IFS= read -r package; do go test -count=1 "$package" done < <( go list ./apps/control-plane/... ./apps/edge/... ./apps/node/... ./packages/go/... ./scripts/... | sed '/^iop\/packages\/go\/agenttask$/d' ) -
client/Flutter, proto, Makefile, script, config 변경이 배포 범위에 포함되면 해당 도메인 규칙의 전체 테스트도 추가한다.
-
전체 테스트가 실패하면 build/deploy를 진행하지 않고 실패 패키지와 핵심 오류를 보고한다.
-
-
전체 rebuild
-
같은 source ref에서 dev-runtime Edge binary, mac node binary, Linux ARM64 node binary, Windows AMD64 node binary를 모두 다시 빌드한다.
-
네 binary 모두
-trimpath로 빌드한다.go build -trimpath -o build/dev-runtime/bin/edge ./apps/edge/cmd/edge go build -trimpath -o build/dev-runtime/bin/iop-node ./apps/node/cmd/node GOOS=linux GOARCH=arm64 go build -trimpath -o build/dev-runtime/bin/iop-node-linux-arm64 ./apps/node/cmd/node GOOS=windows GOARCH=amd64 go build -trimpath -o build/dev-runtime/bin/iop-node-windows-amd64.exe ./apps/node/cmd/node -
stale binary가 의심되거나
config refreshsubcommand, admin port, version 출력이 맞지 않으면 clean sync부터 다시 시작한다. -
go version -m의 module source commit, SHA-256, 산출물 경로, timestamp, 크기, 실행 가능 여부를 기록하고 네 binary가DEPLOY_SHA를 가리키는지 확인한다.
-
-
빌드 후 기본 동작 테스트
- 빌드된 Edge binary로
config check,config refresh --help,config refresh --mode dry-run을 실행한다. openai.enabled=true이면openai.provider_id가 비어 있지 않아야 한다. 누락 시 runtime의 ignorededge.yaml을 현재 provider identity에 맞게 보완하고 원본을 release별 경로로 백업한 뒤 다시config check한다. token과 header는 출력하지 않는다.- 빌드 후에도 4단계의 동일한 순차 package 테스트를 실행한다. 실행하지 못하면 사유와 남은 위험을 보고한다.
- dry-run이
rejected또는 예상 밖restart_required를 반환하면 배포를 멈추고 config diff를 보고한다. - Flutter test/build가 tracked
ios/Flutter/*.xcconfig,macos/Flutter/*.xcconfig에 CocoaPods include를 추가하거나 untrackedios/Podfile,macos/Podfile을 만들 수 있다. proto diff와 구분해 확인한 뒤 이번 검증이 만든 정확한 파일만 원복·제거하고 checkout을 clean으로 되돌린다.
- 빌드된 Edge binary로
-
배포와 재시작
- candidate Edge를 먼저 재시작해
18082,18083,18084,19093listener를 확인한 뒤 Node를 시작한다. 잘못된 config payload로 Node가 non-retryableinternal config error를 받고 종료된 상태에서는 Edge만 고쳐도 Node가 자동 복귀하지 않는다. - Edge와 mac-codex-node(CLI adapter + mac-mlx-vllm provider vllm-mlx process)는 원격 runner에서 빌드 산출물 기준으로 재시작한다.
- GX10 node는 Linux ARM64 node binary를 배포하고 기존 node process를 재시작한다.
- 처음 교체할 때 원본은
pre-<release>로 보존한다. 같은 release의 후속 candidate를 재배포하면 원본 backup을 덮어쓰지 말고 현재 실패 candidate를pre-<release>-<short-sha>로 옮긴 뒤 교체한다. - GX10 Laguna vLLM container를 재생성할 때 host template
/home/toki/iop-gx10-vllm/laguna-s-2.1-thinking.jinja를 container/run/iop/laguna-s-2.1-thinking.jinja에 read-only bind하고--chat-template로 지정한다. stock template로 되돌리면 enabled 요청이 첫 생성 토큰으로</think>를 내보내 Pi thinking이 비는 회귀가 생길 수 있다. - OneXPlayer node는 현재 host에서
ssh r0bin@192.168.0.59로 접속한다. artifact가 remote runner에 있으면 현재 host를 통해 전달한 뒤 Windows host에서 교체한다. - OneXPlayer에서는 SSH 세션 안의
Start-Process로 장기 실행을 시작하지 않는다.Win32_Process.Create또는 동등한 세션 독립 실행 방식으로iop-node.exe --config node.yaml serve를 시작한다. - RTX5090 node는 현재 host에서
ssh iop-dev-rtx5090으로 접속한다. IOP 관련 Windows 부팅 owner는 두지 않고, operator는C:/Users/r0bin/iop-field/remote-llm-toggle.ps1또는 이를 한 번 호출하는RemoteLLM_mode.ahk로 수동 전환한다. IOP dev 배포는 Startup shortcut, Run entry, Task Scheduler, Windows service를 생성하거나 복원하지 않는다. 기본 Toggle은 상태를 반전시키므로 배포 자동화에서 호출하지 말고-Action Status|Up|Down을 명시한다. Node binary만 즉시 재시작할 때는Win32_Process.Create또는 동등한 세션 독립 실행 방식을 사용하고 SSH 세션 내부의Start-Process에 장기 실행을 의존하지 않는다. - RTX5090 Lemonade는
host=0.0.0.0, CUDA backend, Q5 GGUF + Q8 KV, context262144기준을 inventory와 대조한다. localhost-only bind는 Node에서 provider endpoint에 접속할 수 없으므로 배포 완료로 보지 않는다.
- candidate Edge를 먼저 재시작해
-
배포 후 연결 검증
- Edge, OpenAI-compatible listener, Node TCP, admin port, Control Plane status port가 열려 있는지 확인한다.
- Control Plane status에서 Edge가 connected이고 dev-runtime 기준 4개 node가 connected인지 확인한다.
- 각 node의
provider_snapshots에서 providerid,capacity,in_flight,queued,health,served_models를 확인한다. /v1/models가 대상 model alias를 노출하는지 확인한다.
-
Run the OpenAI-compatible capacity smoke
- Qualify
/v1/responsesand/v1/chat/completionsseparately. Do not fail solely because the unimplemented legacy/v1/completionsendpoint is absent. - Use a short request that asks for a structured 700-1200-token answer and explicitly bounds provider-native thinking. Compute the emitted JSON Unicode rune count,
runes/4 + runes/16estimate, and context class. Do not reuse long-context or repetition fixtures as a normal-capacity oracle. - In managed mode, authenticate
GET /v1/credentials/routeswith the same principal token used at OpenAI ingress. Require one active exact route alias. An explicitresource_selectormust intersect with one exact healthy provider snapshot;defaultintersects the route profile/upstream model and model group with every matching healthy provider snapshot. - Run
scripts/e2e-openai-managed-capacity-smoke.shfor one endpoint and route at a time. Require the emitted request to classify asnormal. For an explicit selector, send the selected provider'scapacityplus one request. For adefaultpool, send the sum of every eligible matching provider'scapacityplus one and require each provider's observed peak to reach its own capacity. If it classifies aslong, fail this normal-capacity gate and use the separate long-context admission smoke withlong_context_capacity; never add capacity from a provider excluded by the authenticated route. - Keep current projected Ornith cases separate: qualify the
ornith:35bdefault pool through GX104+ OneXPlayer3with RTX excluded, and qualifyornith-fastonly throughrtx5090-lemonade. Run Chat and Responses independently for each alias. Do not mutate routes, capacities, or timeout values to make the smoke pass. - Require HTTP 200 for every request, exactly one endpoint-native success terminal and one
[DONE]per stream, selected-provider peakin_flightequal to eligible capacity,queued >= 1, and selected final counters0/0. Treat a missing route match, changed capacity, wrong context class, missing status sample, or incomplete terminal as a fail-closed release blocker. - Every invocation must allocate a distinct mode-0700 directory under ignored
agent-test/runs/**. Accept only request/result/status files bound to that invocation's manifest and timestamps. Preserve raw routes, request bodies, response bodies, curl errors, token/header values, route ids, slot ids, prompts, and output only inside that directory; retain only the script's allowlisted sanitized summary as task or tracked evidence. - For unprojected provider pools, retain the existing model-group capacity rule. The current unprojected baseline is Qwen
qwen3.6:35bon mac-mlx-vllm capacity2(three requests). Stopped Laguna is rollback-only and has no active provider capacity. - Allow Qwen and Ornith reasoning/thinking text as normal output. For Ornith, compare Pi
highthinking events withoffzero-thinking events and final text. For agent/tool-call qualification, test forced, automatic, streaming, and multi-turn tool calls separately from capacity qualification.
- Qualify
-
git-flow release finish와 tag 반영
- 빌드 전·후 테스트, 배포 후 연결 검증,
/v1/responses와/v1/chat/completionscapacity smoke가 모두 성공했는지 다시 확인한다. Managed route가 있으면scripts/e2e-openai-managed-capacity-smoke.sh의 네 Ornith route/endpoint case와 current-run provenance gate가 모두 통과해야 한다. - 하나라도 실패했거나 필수 검증이 실행되지 않았으면 finish하지 않고
release/dev-<count>branch를 유지한다. - 현재 release HEAD가
DEPLOY_SHA와 같은지 확인한다. 달라졌으면 배포 산출물과 source가 달라진 것이므로 finish하지 않는다. - finish 직전에
git fetch origin dev main --tags를 다시 실행하고origin/dev=DEV_BASE_SHA,origin/main=MAIN_BASE_SHA, remote tag 없음이 모두 유지되는지 확인한다. 하나라도 달라졌으면 finish하지 않고 release branch를 유지한다. git flow release finish -h에서--keepremote지원 여부를 먼저 확인한다. 지원하면git flow release finish --keepremote -m "Release dev-<count>" dev-<count>를 사용한다. 지원하지 않는 구현에서는-p/--push를 주지 않은git flow release finish -m "Release dev-<count>" dev-<count>가 원격 release branch를 건드리지 않는지 help로 확인한 뒤 사용한다. 옵션 파싱 실패는 ref mutation 전 실패인지 확인하고 같은 명령을 추측해 반복하지 않는다.- 생성된 local
dev-<count>tag의 tree가DEPLOY_TREE와 같은지 확인한다. 다르면 원격에 push하지 않는다. - tag tree가 같으면
git push --atomic origin refs/heads/main:refs/heads/main refs/heads/dev:refs/heads/dev refs/tags/dev-<count>:refs/tags/dev-<count> :refs/heads/release/dev-<count>로 production/develop/tag 반영과 remote release branch 삭제를 한 번에 수행한다. - local finish 검증이나 atomic push가 실패하면
DEPLOY_SHA로 detach한 뒤 localmain=MAIN_BASE_SHA,dev=DEV_BASE_SHA,release/dev-<count>=DEPLOY_SHA를 복원하고 생성된 local tag를 삭제한 다음 release branch로 돌아간다. remote는 atomic push 전 상태여야 한다. - 성공 후 local과 origin의
main,dev반영 상태, local/remote tag 존재, local/remote release branch 삭제를 확인한다. - 원격 runner도
git fetch --prune origin dev main --tags, cleandevsync, local release branch 삭제 순서로 정리한다. ignored runtime config와 build artifact는 삭제하지 않는다.
- 결과 보고
- source ref, clean sync 결과, 테스트 결과, 빌드 산출물, process/port 상태, connected node 목록, provider capacity snapshot, capacity smoke 관측값을 보고한다.
- release version, release branch publish, finish,
main/dev반영, local/remote tag 상태를 보고한다. - 실패한 단계가 있으면 다음 단계를 진행했는지 여부를 명확히 구분한다.
- capacity smoke가 타이밍 문제로 관측 실패했으면 요청 성공과 별도로
capacity 관측 미충족으로 보고하고, 프롬프트 길이 또는 status polling 간격 조정을 제안한다.
재발 차단 진단
| 증상 | 원인 판정 | 조치 |
|---|---|---|
non-login SSH에서 go: command not found |
runner PATH 미초기화 | PATH를 명시하거나 login zsh에서 command -v go/flutter/protoc를 확인한다. |
agentprovider/catalog version probe timeout |
여러 package 동시 실행에 따른 짧은 probe 경합 가능성 | 전체 package를 순차 재실행한다. 순차 실패일 때만 source blocker로 판정한다. |
| Windows cross-build가 Unix file owner 타입에서 실패 | OS별 credential key-file 검증 분리 누락 | packages/go/credentiallease의 Unix/Windows test와 실제 Windows ACL smoke를 통과시킨 뒤 다시 빌드한다. |
Edge 로그의 openai_compat adapter instance key "<provider-id>" conflicts with provider id |
profile-backed provider와 같은 이름의 정상 backing을 중복 emit하는 mapper 또는 stale Edge | provider/adapter 설정이나 agent orchestration을 삭제하지 않는다. go test -race ./apps/edge/internal/node와 candidate Edge source identity를 확인하고 Edge를 rebuild/restart한다. |
Node가 internal config error 후 재접속하지 않음 |
config rejection은 일시 네트워크 단절과 달리 process를 종료할 수 있음 | fixed Edge를 먼저 올린 뒤 mac/GX10/OneXPlayer/RTX5090 Node를 각각 다시 시작한다. |
Edge service test 종료 후 in_flight가 남음 |
같은 clock 값에서 run ID가 충돌한 회귀 가능성 | go test -race ./apps/edge/internal/service와 run ID 동시성 회귀 테스트를 확인한다. |
git flow release finish --keepremote가 option parse 단계에서 실패 |
설치된 git-flow 구현이 해당 long option을 지원하지 않음 | ref 무변경을 확인하고 help에 따라 no-push finish를 사용한 뒤 atomic push에서 release 삭제를 수행한다. |
위 오류는 dev-runtime Edge/Node 배포 문제다. 이를 통과시키기 위해 agent-ops/rules/common/**, common orchestration dispatch.py, apps/agent/**를 수정·삭제하지 않는다.
실행 결과 검증
- 원격 runner local
dev가origin/dev로 clean sync되었는가 origin/main이origin/dev의 ancestor이고 localmain/dev가 원격 기준과 일치하는가devHEAD commit count로dev-<count>version을 계산했는가release/dev-<count>branch를 새로 게시했거나 동일 version의 기존 branch를 안전하게 재개했는가- 빌드 전 dev-runtime 범위의 순차 Go 테스트와 필요한 추가 전체 테스트가 통과했는가
- dev-runtime Edge/mac/Linux ARM64/Windows AMD64 binary가 같은 release branch commit에서 rebuild되었는가
- 빌드 후 config check, refresh help, refresh dry-run, 전체 테스트가 통과했는가
- Edge, mac-codex-node, GX10 vLLM node, OneXPlayer Lemonade node, RTX5090 Lemonade node가 재시작되고 4개 node(mac-codex, gx10-vllm, onexplayer-lemonade, rtx5090-lemonade)가 connected 상태인가
- OneXPlayer 접속과 실행이
r0bin@192.168.0.59및 세션 독립 실행 방식으로 수행되었는가 - RTX5090 접속이
ssh iop-dev-rtx5090public-key batch 인증으로 성공하고, IOP 관련 boot autostart가 없으며, 수동 toggle의 exact Ornith profile·0.0.0.0:13305listener·Node Edge 연결이 확인되고 Startup/Run/Task/Service 항목을 생성하지 않았는가. /v1/responsescapacity smoke에서 총 capacity만큼in_flight가 차고 초과 요청이 queue에 잡혔는가/v1/chat/completionscapacity smoke에서 총 capacity만큼in_flight가 차고 초과 요청이 queue에 잡혔는가- 완료 후 provider
in_flight=0,queued=0으로 회복되었는가 - 모든 필수 검증 성공 후에만 release finish를 실행했는가
- finish 직전 origin
main/dev가 시작 시점 SHA와 같은지 재검증했는가 dev-<count>tag tree가 실제 배포한 release tree와 같은가- atomic push로 origin
main/dev와 tag가 함께 반영되고 remote release branch가 삭제되었는가 - 검증 실패 시: 실패 단계, 실패한 host/provider/endpoint, 관측된 snapshot, 진행 중단 여부를 보고한다.
출력 형식
dev-runtime 배포 결과
- Release: version=<dev-count>, branch=<release/dev-count>, finish=<done|not-run|partial>, tag=<local/remote status>
- Source: <branch/ref/commit>, clean=<yes|no>
- Pre-build tests: <command> - <pass|fail|not-run>
- Build: edge=<path>, mac-node=<path>, linux-arm64-node=<path>, windows-amd64-node=<path>
- Post-build checks: config-check=<pass|fail>, refresh-help=<pass|fail>, refresh-dry-run=<status>, tests=<pass|fail|not-run>
- Deployment: edge=<pid/status>, mac-node=<pid/status>, gx10=<pid/status>, onexplayer=<pid/status>, rtx5090=<pid/status>
- Ports: <port summary>
- Nodes: <node_id connected summary>
- Providers: <provider_id capacity/in_flight/queued/health summary>
- OpenAI-compatible: models=<pass|fail>, responses-capacity=<pass|fail>, chat-completions-capacity=<pass|fail>
- Capacity evidence: <endpoint별 max in_flight/queued snapshot>
- Blockers/Risk: <없음 또는 내용>
금지 사항
- dirty checkout이나 stale binary를 그대로 배포하지 않는다.
git clean -fdx를 기본 cleanup으로 사용하지 않는다.dev이외의 branch나 임의 source ref를 dev release 기준으로 사용하지 않는다.- shallow clone이나
origin/dev와 HEAD가 다른 상태에서 release version을 계산하지 않는다. origin/main이origin/dev의 ancestor가 아닌 상태에서 release를 시작하지 않는다.- 기존 tag를 자동 삭제, 이동, 덮어쓰기하지 않는다.
- 같은 release의 local/remote branch가 diverge한 상태를 자동 reset하지 않는다.
- 빌드 전 전체 테스트 실패 후 배포를 계속하지 않는다.
- 필수 테스트, 배포 후 연결 검증, capacity smoke 중 하나라도 실패하거나 실행되지 않았는데 release를 finish하거나 tag를 생성하지 않는다.
- tag tree와 실제 배포 tree가 다른 상태에서 원격 tag를 push하지 않는다.
main,dev, tag를 개별 push하여 원격에 partial finish 상태를 만들지 않는다.- OneXPlayer에
toki사용자명으로 접속하거나 remote runner에서 다시 OneXPlayer로 SSH 접속하지 않는다. - OneXPlayer 장기 실행을 Windows OpenSSH 세션 내부
Start-Process에 의존하지 않는다. - RTX5090 Node용 Windows Task Scheduler 항목을 생성하거나 재생성하지 않는다.
- Qwen reasoning/thinking 출력을 실패로 판정하거나 exact-output smoke를 기본 성공 기준으로 삼지 않는다.
- Qwen provider를 agent/tool-call 용도로 쓰면서 provider별
--tool-call-parser/--chat-template검증 없이 배포 완료로 선언하지 않는다. - OpenAI-compatible 요청 성공만으로 capacity 검증 성공을 선언하지 않는다. provider snapshot의
in_flight/queued관측을 함께 남긴다. - 이 프로젝트 전용 배포 절차를
agent-ops/rules/common/_templates또는 common skill에 넣지 않는다.