제품 결과와 harness·process·artifact 실패가 하나의 성공 값으로 덮이지 않도록 durable evidence와 모든 소비자 계약을 함께 마이그레이션한다.
32 KiB
Agent Comparison Benchmark Dev Guide
이 문서는 IOP one-shot agent/model comparison benchmark의 현재 구현, dev 환경 구성, caller 연결 방식, managed credential 경계, 실행 절차와 장애 대응 기준을 한곳에 모은 운영 가이드다.
raw token, provider API key, private key, slot alias, lease id와 개인 endpoint는 이 문서에 기록하지 않는다. 실제 host, checkout, Node/provider endpoint와 최신 process 상태는 아래 source of truth에서 확인한다.
- benchmark manifest:
scripts/fixtures/agent-comparison-benchmark-iop-one-shot.json - public CLI:
scripts/agent_comparison_benchmark.py - dev environment:
agent-test/dev/rules.md - machine-readable dev inventory:
agent-test/inventory-dev.yaml - Edge/Node verification:
agent-test/dev/edge-smoke.md,agent-test/dev/node-smoke.md - API contracts:
agent-contract/outer/anthropic-compatible-api.md,agent-contract/outer/openai-compatible-api.md,agent-contract/outer/gemini-compatible-api.md - benchmark SDD:
agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-one-shot-agent-model-comparison/SDD.md
이 문서는 위 계약과 manifest를 설명할 뿐 덮어쓰지 않는다. 값이 다르면 manifest, contract, inventory, environment rule 순서로 최신 상태를 확인한다.
1. 현재 상태
2026-08-12 기준 상태는 다음과 같다.
| 영역 | 상태 |
|---|---|
| Gemini-native Edge ingress | 구현 완료. route-qualified streamGenerateContent, x-goog-api-key IOP principal auth, request/tool/SSE 변환을 지원한다. |
| official agy adapter | 구현 완료. agy 1.1.12, Gemini API-key provider, real init/step_update/result JSONL을 사용한다. |
| managed dev credential runtime | 구성 완료. Control Plane projection, credential slot/route, sealed lease, Edge HTTPS, CP↔Edge/Edge↔Node mTLS를 사용한다. |
| caller readiness | 최근 완료된 readiness evidence에서 C01-C09 ready=9를 확인했다. 실제 실행일에는 fresh preflight가 다시 필요하다. |
| controller recovery | control socket symlink와 caller launch 전 interruption 회귀 수정 및 테스트가 완료됐다. |
| Codex production JSONL | cache_write_input_tokens 수용과 config-owned effective binding 정합화가 완료됐다. |
| deterministic tests | focused 41 tests, 전체 benchmark 429 tests가 통과했다. 숫자는 당시 snapshot이며 현재 suite 결과는 fresh 실행으로 판단한다. |
| C01-C09 scored execution | 아직 완료되지 않았다. 과거 incomplete/failed run은 append-only evidence로 보존하며 정상 결과로 간주하지 않는다. |
| blind scoring/report | 유효한 9-cell execution이 생긴 뒤 수행하는 후속 단계다. |
과거 실행 실패는 새 run을 정당화하는 완료 evidence가 아니다. 이전 run tree를 수정하거나 old run을 암묵적으로 resume/retry하지 않는다. 새 scored execution은 그 실행을 명시적으로 소유하는 현재 plan과 사용자 권한이 있을 때만 한 번 수행한다. 이 문서 자체는 지속적 실행 승인을 부여하지 않는다.
2. 시스템 구성
Benchmark runner
├─ Claude Code ── Anthropic Messages ───────────────┐
├─ agy ───────── Gemini streamGenerateContent ─────┤
└─ Codex ─────── OpenAI Responses ─────────────────┤
v
IOP Edge HTTPS
│
┌───────────────────────────┴───────────────────────────┐
│ │
direct model route execution preset
│ selector/plan/work/review/repair
└───────────────────────────┬───────────────────────────┘
v
managed credential lease
Control Plane projection + Node sealed lease
│
v
Node-owned provider
핵심 보안 경계는 다음과 같다.
- benchmark caller는 하나의 IOP principal token으로 Edge만 인증한다.
- caller token은 upstream provider credential이 아니다.
- provider credential은 Control Plane에 등록된 slot과 Node 대상 sealed lease에서만 온다.
- Edge는 provider credential을 복호화하지 않고 caller가 보낸 token을 upstream auth로 재사용하지 않는다.
- managed mode는 legacy static principal/provider credential과 혼용하지 않는다.
- config observation은 secret이 아닌 route/model/stage binding의 독립 증거다.
3. 환경 프로필
3.1 Benchmark runner
현재 검증된 runner class는 Linux/AArch64다. 명령은 repository root에서 실행한다.
필수 command:
command -v python3
command -v git
command -v claude
command -v agy
command -v codex
2026-08-12 확인 snapshot:
| Tool | 확인된 버전 | 정책 |
|---|---|---|
| Claude Code | 2.1.228 |
고정 버전으로 추정하지 않고 매 execution preflight에서 --version/--help를 확인한다. |
| agy | 1.1.12 |
adapter가 이 버전을 명시적으로 gate한다. 다른 버전은 재검증 전 fail closed한다. |
| Codex CLI | 0.147.0 |
고정 버전으로 추정하지 않고 매 execution preflight에서 --version과 exec --help를 확인한다. |
3.2 Testbed
- path:
../iop-s2 - 현재 확인 branch:
dev - 현재 확인 상태: clean
- benchmark는 testbed를 read-only provenance로 취급한다.
- caller별 workspace와 session은 run tree 아래에 새로 만들며 서로 공유하지 않는다.
- testbed를 benchmark 결과로 수정하거나 결과 파일을 다시 복사하지 않는다.
fixture checksum과 source file 목록은 manifest가 고정한다. testbed HEAD와 clean 상태는 실행일에 다시 확인한다.
3.3 Dev runtime
현재 검증된 runtime class는 macOS/ARM64 remote dev runner다. exact SSH target과 checkout은 agent-test/dev/rules.md 및 agent-test/inventory-dev.yaml을 따른다.
benchmark 관련 runtime 역할:
| Port | 역할 |
|---|---|
18082 |
Edge artifact/bootstrap HTTP |
18083 |
managed Edge public HTTPS; Anthropic/OpenAI/Gemini caller ingress |
18084 |
native dev-runtime Edge↔Node TCP |
19093 |
Edge admin/config refresh |
19101 |
Edge metrics |
2026-08-12 read-only 확인에서 위 listener와 managed Edge process는 모두 active였고 remote checkout은 clean release 상태였다. exact commit, binary checksum, process id와 endpoint는 실행 evidence에만 기록하고 이 가이드에 고정하지 않는다.
최근 완료된 live readiness evidence는 4 connected Nodes와 8 healthy/available providers를 확인했다. 최신 Node/provider 세부와 접속 위치는 반드시 agent-test/inventory-dev.yaml에서 다시 확인한다.
이 benchmark는 compose dev stack의 Edge-Node TCP 19003이 아니라 native dev-runtime provider pool의 18084를 사용한다. compose와 native profile은 포트, process와 판정 evidence가 서로 다르므로 한 실행에서 섞지 않는다. 현재 inventory가 가리키는 배포 산출물은 다음과 같다.
| Artifact | Path |
|---|---|
| native Edge config | build/dev-runtime/edge.yaml |
| Edge binary | build/dev-runtime/bin/edge |
| macOS Node binary | build/dev-runtime/bin/iop-node |
| Linux ARM64 Node binary | build/dev-runtime/bin/iop-node-linux-arm64 |
| Windows AMD64 Node binary | build/dev-runtime/bin/iop-node-windows-amd64.exe |
모든 Edge/Node binary는 scored execution 전에 동일 source ref로 rebuild·redeploy·restart한다. build/dev-runtime/**의 runtime config와 untracked credential material은 원격 runner가 소유하며 tracked 문서나 testbed로 복사하지 않는다.
4. 보호 파일과 credential 역할
benchmark runner의 token/ 아래에는 다음 파일이 준비돼 있다. 파일 존재와 mode만 확인하며 내용을 출력하지 않는다.
| Path | 역할 | 실행 시 사용 |
|---|---|---|
token/.iop-bench |
benchmark용 IOP principal token | preflight/run/score caller가 Edge를 인증할 때 사용 |
token/iop-dev-ca.pem |
managed dev Edge HTTPS CA certificate | SSL_CERT_FILE, NODE_EXTRA_CA_CERTS로 전달 |
token/.claude |
Claude provider credential의 초기 provisioning source | provider slot 등록 시에만 사용; benchmark caller에 전달하지 않음 |
token/.gemini |
Gemini provider credential의 초기 provisioning source | provider slot 등록 시에만 사용; benchmark caller에 전달하지 않음 |
token/.gpt |
GPT provider credential의 초기 provisioning source | provider slot 등록 시에만 사용; benchmark caller에 전달하지 않음 |
현재 secret source 파일은 0600, CA certificate는 0644로 확인됐다. CA certificate는 public trust material이지만 private key는 아니다.
안전 확인:
for benchmark_secret_file in token/.iop-bench token/.claude token/.gemini token/.gpt; do
test -f "$benchmark_secret_file"
test "$(stat -c '%a' "$benchmark_secret_file")" = 600
done
test -f token/iop-dev-ca.pem
macOS에서 동일 검사를 수행할 때는 BSD stat 문법을 사용한다. 어떤 경우에도 cat, echo, shell tracing(set -x)으로 secret 내용을 출력하지 않는다.
5. Provider와 managed credential 설정
현재 dev 구성은 다음 절차로 만들어졌다.
- Control Plane credential plane용 CA, workload certificate, at-rest keyring과 lease issuer/recipient key를 operator-owned untracked 경로에 생성했다.
- Control Plane, Edge와 각 Node에 role/name-bound mTLS identity를 배치했다.
- Edge public ingress를 HTTPS로 구성하고 benchmark runner에 CA certificate만 전달했다.
- benchmark principal을 bootstrap하고 one-time token을
token/.iop-bench에 저장했다. token/.claude,token/.gemini,token/.gpt의 raw provider key를 credential HTTPS request body로 직접 등록했다. command argument, YAML, tracked docs나 task evidence에는 넣지 않았다.- credential slot과 public route를 별도로 생성하고 principal projection에 direct route와 hybrid preset stage authorization을 연결했다.
- Control Plane → Edge → Nodes 순서로 bounded restart하고 fresh projection, sealed lease, route revision과 no-fallback 동작을 검증했다.
재구성이 필요하면 docs/edge-local-dev-guide.md의 “Managed credential plane and TLS startup”과 “Safe slot lifecycle”을 따른다. 실제 slot id, alias, revision과 lease id는 운영 상태이므로 이 문서에 복사하지 않는다.
6. Caller별 연결 방식
| Caller | Edge surface | Child 설정 | 중요한 제한 |
|---|---|---|---|
| Claude Code | Anthropic-compatible Messages | ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY; --bare --print --verbose --output-format stream-json --no-session-persistence --permission-mode dontAsk --tools Read,Write,Edit --allowedTools Read,Write,Edit |
task는 stdin으로 한 번 제출한다. network/shell 도구 없이 격리 workspace 파일 작업만 허용한다. model/effort는 manifest 값을 그대로 전달한다. |
| agy | Gemini-native streamGenerateContent |
fresh session HOME, GOOGLE_GEMINI_BASE_URL, GEMINI_API_KEY; --sandbox --output-format stream-json --model ... --print ... |
agy 1.1.12만 승인된다. API-key provider에 --effort를 전달하지 않으며 ambient user config를 읽지 않는다. |
| Codex | OpenAI-compatible Responses | fresh session HOME, isolated iop_benchmark provider override, IOP_BENCHMARK_API_KEY; exec --sandbox workspace-write --json --ephemeral --ignore-user-config --strict-config |
user config를 읽지 않고 격리 workspace에만 쓸 수 있다. current adapter effort는 xhigh; caller binding event가 없으면 admitted config binding을 사용하고, 보고된 mismatch는 거부한다. |
세 caller child에는 필요한 PATH와 CA 변수만 allowlist로 전달한다. parent의 caller/provider 설정이나 unrelated secret은 상속하지 않는다.
agy의 public base는 adapter가 cell별로 다음처럼 route-qualified 한다.
<edge-origin>/gemini/<route-id>
GEMINI_BASE_URL, AGY_PROVIDER, AGY_OPENAI_BASE_URL, AGY_OPENAI_API_KEY는 이 benchmark transport가 아니다.
official agy planner가 Gemini generationConfig.responseMimeType과 responseSchema 또는 responseJsonSchema를 보내면 Edge는 이를 기존 Chat response_format으로 변환한다. function declaration은 official SDK가 사용하는 parameters와 parametersJsonSchema 표기 중 정확히 하나를 허용한다. 동의어 필드가 동시에 있거나 schema가 JSON object가 아니면 provider dispatch 전에 거부한다. 구조가 유효한 agy result.status=ERROR는 stream parser 오류로 바꾸지 않고 caller process 실패로 기록한다.
7. Benchmark 고정 설정
| 설정 | 값 |
|---|---|
| pipeline version | 2 |
| environment | dev |
| execution seed | bench-02-c01-c09-v1 |
| repetitions | 1 |
| session policy | fresh |
| setup cache policy | isolated |
| run timeout | 300 seconds |
| idle timeout | 30 seconds |
| quiet window | 10 seconds |
| cleanup grace | 5 seconds |
| desktop viewport | 1920x1080 |
| mobile viewport | 375x812 |
| output root | agent-test/runs/bench-02 |
| rubric | one-shot-agent-comparison-v1 |
execution seed로 결정되는 현재 slot 순서는 다음과 같다. 표의 C 번호 순서와 실제 실행 순서는 다르다.
- C02 Claude→Gemini direct
- C05 Codex→GPT direct
- C03 agy→Gemini direct
- C06 Claude→Gemini hybrid
- C08 Claude→GPT hybrid
- C09 Codex→GPT hybrid
- C01 Claude→Sonnet direct
- C07 agy→Gemini hybrid
- C04 Claude→GPT direct
8. C01-C09 matrix와 route binding
| Cell | Caller | Route kind/id | Requested model/effort | Effective stage binding |
|---|---|---|---|---|
| C01 | Claude | direct / claude-sonnet-5 |
claude-sonnet-5 / max |
request=claude-sonnet-5 max |
| C02 | Claude | direct / gemini-3.6-flash |
gemini-3.6-flash / high |
request=gemini-3.6-flash high |
| C03 | agy | direct / gemini-3.6-flash |
gemini-3.6-flash / high |
request=gemini-3.6-flash high |
| C04 | Claude | direct / gpt-5.6-luna |
gpt-5.6-luna / xhigh |
request=gpt-5.6-luna xhigh |
| C05 | Codex | direct / gpt-5.6-luna |
gpt-5.6-luna / xhigh |
request=gpt-5.6-luna xhigh |
| C06 | Claude | preset / gemini-hybrid |
gemini-hybrid / high |
selector/plan/review/repair=gemini-3.6-flash high; work=ornith-fast |
| C07 | agy | preset / gemini-hybrid |
gemini-hybrid / high |
selector/plan/review/repair=gemini-3.6-flash high; work=ornith-fast |
| C08 | Claude | preset / gpt-hybrid |
gpt-hybrid / xhigh |
selector/plan/review/repair=gpt-5.6-terra high; work=ornith-fast |
| C09 | Codex | preset / gpt-hybrid |
gpt-hybrid / xhigh |
selector/plan/review/repair=gpt-5.6-terra high; work=ornith-fast |
hybrid preset은 caller가 stage를 따로 호출하는 구조가 아니다. 하나의 caller request 안에서 Edge가 selector/plan/work/review/repair를 소유한다.
9. Fixture와 결과 조건
공통 task는 fictional product “Lumen Atlas”의 responsive one-page landing page다.
- prompt:
scripts/fixtures/agent-comparison-benchmark/prompt.md - copy:
scripts/fixtures/agent-comparison-benchmark/reference.txt - images:
aurora-grid.svg,orbit-rings.svg - 생성 파일: workspace root의
index.html,styles.css,script.js정확히 세 개 - 외부 asset, framework, package manager, build tool, analytics와 network dependency 금지
- desktop/mobile responsive, semantic HTML, focus/contrast/accessibility 요구
- 각 attempt는 fresh workspace/session에서 task를 한 번만 제출
fixture checksum은 manifest의 값이 유일한 기준이다. prompt나 asset을 변경하면 기존 run과 비교하지 말고 manifest/version/checksum을 함께 갱신하는 별도 작업으로 처리한다.
10. Process environment 준비
다음은 value를 출력하지 않는 process-local 예시다. <edge-host>를 문서에 실제 값으로 치환하지 말고 실행 환경에서만 주입한다.
Public live registry가 소비하는 environment contract는 다음과 같다.
| Variable | 값/의미 | Durable evidence |
|---|---|---|
IOP_BENCH_CLAUDE_BASE_URL |
managed Edge HTTPS origin | raw 값 금지; endpoint digest만 허용 |
IOP_BENCH_AGY_BASE_URL |
managed Edge HTTPS origin; adapter가 /gemini/<route-id>를 추가 |
raw 값 금지; endpoint digest만 허용 |
IOP_BENCH_CODEX_BASE_URL |
managed Edge OpenAI-compatible /v1 base |
raw 값 금지; endpoint digest만 허용 |
IOP_BENCH_CLAUDE_SECRET_ENV |
Claude가 사용할 secret-bearing variable 이름 | variable 이름만 허용 |
IOP_BENCH_AGY_SECRET_ENV |
agy가 사용할 secret-bearing variable 이름 | variable 이름만 허용 |
IOP_BENCH_CODEX_SECRET_ENV |
Codex가 사용할 secret-bearing variable 이름 | variable 이름만 허용 |
IOP_BENCH_SHARED_TOKEN |
이 가이드 예시의 secret-bearing variable | 값 기록 금지 |
SSL_CERT_FILE |
dev Edge HTTPS CA certificate path | repository-relative file reference만 허용 |
NODE_EXTRA_CA_CERTS |
Node.js caller용 동일 CA certificate path | repository-relative file reference만 허용 |
IOP_BENCH_CONFIG_OBSERVATION_ENV |
config JSON을 보유한 variable 이름 | variable 이름만 허용 |
BENCH_CONFIG |
schema v1 route/model/stage observation JSON | secret은 없지만 runtime과 일치하는 canonical digest만 evidence에 기록 |
PATH |
caller binary resolution | resolved executable path/version만 preflight에서 확인 |
Child adapter가 내부적으로 만드는 값은 caller별로 격리된다.
- Claude:
ANTHROPIC_BASE_URL,ANTHROPIC_API_KEY, restrictedRead,Write,Edit, nonessential traffic/autoupdater disable flags와 CA variables - agy: fresh session
HOME,GOOGLE_GEMINI_BASE_URL,GEMINI_API_KEY,LANG=C.UTF-8,LC_ALL=C.UTF-8,TZ=UTC와 CA variables - Codex: fresh session
HOME,IOP_BENCHMARK_API_KEY, strict ephemeral provider override와 CA variables
이 child variable은 사용자가 별도로 준비할 값이 아니다. live registry가 위 public contract에서 파생하며, parent의 같은 이름 값을 그대로 신뢰하거나 상속하지 않는다.
set -euo pipefail
benchmark_edge_origin="${BENCHMARK_EDGE_ORIGIN:?set BENCHMARK_EDGE_ORIGIN to the managed dev Edge HTTPS origin}"
read -r IOP_BENCH_SHARED_TOKEN < token/.iop-bench
export IOP_BENCH_SHARED_TOKEN
export IOP_BENCH_CLAUDE_BASE_URL="$benchmark_edge_origin"
export IOP_BENCH_AGY_BASE_URL="$benchmark_edge_origin"
export IOP_BENCH_CODEX_BASE_URL="$benchmark_edge_origin/v1"
export IOP_BENCH_CLAUDE_SECRET_ENV=IOP_BENCH_SHARED_TOKEN
export IOP_BENCH_AGY_SECRET_ENV=IOP_BENCH_SHARED_TOKEN
export IOP_BENCH_CODEX_SECRET_ENV=IOP_BENCH_SHARED_TOKEN
export SSL_CERT_FILE="$PWD/token/iop-dev-ca.pem"
export NODE_EXTRA_CA_CERTS="$PWD/token/iop-dev-ca.pem"
export IOP_BENCH_CONFIG_OBSERVATION_ENV=BENCH_CONFIG
BENCH_CONFIG="$(python3 - <<'PY'
import json
routes = [
{"route_kind":"direct","route_id":"claude-sonnet-5","model":"claude-sonnet-5","bindings":[{"stage":"request","model":"claude-sonnet-5","effort":"max"}]},
{"route_kind":"direct","route_id":"gemini-3.6-flash","model":"gemini-3.6-flash","bindings":[{"stage":"request","model":"gemini-3.6-flash","effort":"high"}]},
{"route_kind":"direct","route_id":"gpt-5.6-luna","model":"gpt-5.6-luna","bindings":[{"stage":"request","model":"gpt-5.6-luna","effort":"xhigh"}]},
{"route_kind":"execution_preset","route_id":"gemini-hybrid","model":"gemini-hybrid","bindings":[{"stage":"selector","model":"gemini-3.6-flash","effort":"high"},{"stage":"plan","model":"gemini-3.6-flash","effort":"high"},{"stage":"work","model":"ornith-fast","effort":None},{"stage":"review","model":"gemini-3.6-flash","effort":"high"},{"stage":"repair","model":"gemini-3.6-flash","effort":"high"}]},
{"route_kind":"execution_preset","route_id":"gpt-hybrid","model":"gpt-hybrid","bindings":[{"stage":"selector","model":"gpt-5.6-terra","effort":"high"},{"stage":"plan","model":"gpt-5.6-terra","effort":"high"},{"stage":"work","model":"ornith-fast","effort":None},{"stage":"review","model":"gpt-5.6-terra","effort":"high"},{"stage":"repair","model":"gpt-5.6-terra","effort":"high"}]},
]
print(json.dumps({"schema_version":"1","routes":routes}, separators=(",",":")))
PY
)"
export BENCH_CONFIG
중요한 의미:
IOP_BENCH_*_SECRET_ENV의 값은 secret이 아니라 실제 secret을 보유한 environment variable의 이름이다.- 세 caller는 같은 IOP principal을 사용하지만 서로 다른 protocol base를 받는다.
BENCH_CONFIG는 runtime에서 독립적으로 확인한 route/stage snapshot이어야 한다. manifest를 보고 임의 합성한 값을 live readiness evidence로 사용하면 안 된다.- endpoint와 config는 evidence에 raw 값 대신 digest identity로만 남는다.
작업 후에는 같은 shell에서 다음 변수를 제거한다.
unset IOP_BENCH_SHARED_TOKEN
unset IOP_BENCH_CLAUDE_BASE_URL IOP_BENCH_AGY_BASE_URL IOP_BENCH_CODEX_BASE_URL
unset IOP_BENCH_CLAUDE_SECRET_ENV IOP_BENCH_AGY_SECRET_ENV IOP_BENCH_CODEX_SECRET_ENV
unset IOP_BENCH_CONFIG_OBSERVATION_ENV BENCH_CONFIG
unset SSL_CERT_FILE NODE_EXTRA_CA_CERTS
unset BENCHMARK_EDGE_ORIGIN benchmark_edge_origin
11. 실행 절차
manifest path는 모든 명령에서 동일하게 사용한다.
benchmark_manifest=scripts/fixtures/agent-comparison-benchmark-iop-one-shot.json
11.1 Source와 deterministic verification
python3 -m unittest scripts.agent_benchmark.codex_iop_test scripts.agent_benchmark.connectivity_integration_test
python3 -m unittest discover -s scripts/agent_benchmark -p '*_test.py'
python3 scripts/agent_comparison_benchmark.py validate --manifest "$benchmark_manifest"
git diff --check
필요하면 변경 범위에 따라 Go tests와 managed credential qualification도 실행한다.
go test -count=1 ./...
credential_smoke_parent="$(mktemp -d /tmp/iop-benchmark-credential.XXXXXX)"
TMPDIR="$credential_smoke_parent" make test-credential-slot-smoke
rmdir "$credential_smoke_parent"
11.2 Direct-first qualification
동일 clean source ref를 모든 runtime binary에 배포하고 4/4 Node와 provider health를 확인한 다음, 먼저 기존 5-cell direct manifest를 사용한다.
direct_manifest="scripts/fixtures/agent-comparison-benchmark-direct-preflight.example.json"
python3 scripts/agent_comparison_benchmark.py preflight --manifest "$direct_manifest"
python3 scripts/agent_comparison_benchmark.py run --manifest "$direct_manifest"
direct canary는 unscored이며 각 최신 slot의 product=succeeded, harness=passed, process=exited/exit 0/no signal, artifact=passed가 모두 5/5여야 한다. running, interrupted, unresolved는 0이어야 한다. 실패 시 hybrid 또는 9-cell scored run을 할당하지 않는다.
11.3 Public nine-cell preflight
10절의 환경을 같은 shell에 준비한 뒤 실행한다.
python3 scripts/agent_comparison_benchmark.py preflight --manifest "$benchmark_manifest"
성공 조건:
status=ready ready=9 registration_required=0 implementation_gap=0
preflight는 다음을 함께 확인한다.
- caller binary/version/help
- Edge model catalog
- principal auth와 endpoint compatibility
- direct/preset route 존재
- requested model/effort
- exact stage binding과 order
- official agy transport capability
registration_required 또는 implementation_gap이면 즉시 중단한다. alias, model, effort, route나 caller를 대체하지 않는다. preflight-only run root는 evidence이므로 삭제하지 않는다.
direct canary 5/5 뒤 fresh one-shot preflight가 ready=9인지 확인하고 멈춘다. 이 qualification 단계에서는 hybrid canary나 C01-C09 run을 호출하지 않는다.
11.4 Scored execution
fresh preflight와 명시적 실행 권한이 있는 현재 plan에서만 다음 명령을 한 번 호출한다.
python3 scripts/agent_comparison_benchmark.py run --manifest "$benchmark_manifest"
- direct CLI stdout/stderr와 exit code를 보존한다.
- CLI가 출력한 canonical
run-...id만 이후status,score,report에 사용한다. - command가 nonzero여도 같은 plan에서
run을 다시 호출하지 않는다. - CLI가 run id를 출력하지 않으면 임의 id나 성공 pointer를 만들지 않는다.
- caller나 provider를 CLI 밖에서 별도로 호출해 scored result를 보충하지 않는다.
11.5 Status
python3 scripts/agent_comparison_benchmark.py status \
--manifest "$benchmark_manifest" \
--run-id "$benchmark_run_id"
현재 comparison execution 완료 조건:
- controller terminal 수
completed + timed_out + cancelled + interrupted = 9 running = 0interrupted = 0- 각 cell/repetition에 retained terminal attempt가 존재
- 최신 attempt에서
product_succeeded=9,harness_passed=9,process_exited=9,artifact_passed=9,unresolved=0
completed는 controller 종료만 뜻하며 product 성공을 뜻하지 않는다. product/harness/process/artifact 실패는 scoring eligibility와 최종 비교에서 각각 별도로 표시된다.
11.6 Blind scoring
유효한 execution run에 대해서만 수행한다.
python3 scripts/agent_comparison_benchmark.py score \
--manifest "$benchmark_manifest" \
--run-id "$benchmark_run_id"
evaluator는 Codex→gpt-5.6-luna xhigh direct route다. identity가 제거된 blind workspace만 보며 source cell identity mapping은 blind tree 밖에 유지한다.
product, harness, acceptable process 또는 artifact gate 실패는 각각의 reason을 가진 unscored이고 0점으로 바꾸지 않는다. scoring_failed도 명시적 --retry-scoring-failed 권한 없이 재시도하지 않는다.
11.7 Report
python3 scripts/agent_comparison_benchmark.py report \
--manifest "$benchmark_manifest" \
--run-id "$benchmark_run_id"
report는 run root의 immutable evidence를 읽어 idempotent report.md를 만든다. 기존 report 내용과 새 projection이 다르면 덮어쓰지 않고 실패한다.
12. 수집 evidence
각 attempt는 다음 범주의 evidence를 가진다.
| 범주 | 내용 |
|---|---|
| lifecycle | typed caller terminal, submission, first output, finish, idle, quiet와 독립 product/harness/process 결과 |
| timeline | submitted, first output, first workspace write observation/mtime, total duration |
| usage | input/output/reasoning/cache read/cache write/total tokens, model/tool calls와 duration |
| workspace | fresh session identity, fixture checksum, testbed provenance, generated file tree |
| web validation | product/harness 결과와 무관하게 모든 terminal workspace에서 생성되는 generated files, static safety, images, network, console, responsive, accessibility |
| screenshots | desktop 1920x1080, mobile 375x812 |
| scoring | eligibility, blind allocation, rubric worksheet, score status |
caller가 보고하지 않은 metric은 0으로 만들지 않고 unavailable과 reason/source를 보존한다.
Codex current usage mapping:
| Caller JSONL field | Canonical metric |
|---|---|
input_tokens |
input_tokens |
cached_input_tokens |
cached_input_tokens |
cache_write_input_tokens |
cache_write_tokens |
output_tokens |
output_tokens |
reasoning_output_tokens |
reasoning_tokens |
total_tokens |
total_tokens |
누락된 total_tokens는 하위 category 합으로 재구성하지 않는다.
13. 자동 gate와 100점 rubric
automatic web gates는 scoring eligibility만 결정하고 점수에 포함되지 않는다.
| Gate |
|---|
| generated files |
| static safety |
| local images |
| no external network dependency |
| console safety |
| responsive layout |
| accessibility |
quality rubric:
| Category | Max |
|---|---|
| requirements fidelity | 25 |
| visual completeness | 25 |
| responsive accessibility | 15 |
| image/detail usage | 10 |
| behavior stability | 10 |
| code quality | 10 |
| self verification | 5 |
| Total | 100 |
14. 실패 처리와 재개 원칙
| 상황 | 조치 |
|---|---|
| manifest invalid | source/manifest를 수정하고 validate부터 다시 시작한다. run을 만들지 않는다. |
| preflight not ready | blocker를 해결하고 fresh preflight한다. attempt를 할당하지 않는다. |
| caller launch 전 interruption | retained evidence를 보존한다. run tree를 직접 수정하지 않는다. |
| lifecycle/parser failure | exact retained output으로 source 원인을 수정하고 deterministic regression을 추가한다. |
| completed이지만 product/harness/process/artifact gate 실패 또는 timed_out/cancelled | 각 축 evidence로 보존한다. 암묵 retry하지 않는다. |
state가 running이지만 process가 없음 |
manual JSON 수정/삭제/reconcile을 하지 않는다. reviewer evidence로 남기고 승인된 새 plan에서만 다음 상태를 결정한다. |
| scoring_failed | 0점 처리하지 않는다. 명시적 retry 권한 없이는 중단한다. |
| report unavailable | run evidence를 수정하거나 report를 수작업 생성하지 않는다. |
현재 milestone의 원칙은 old incomplete/failed run을 resume --retry-failed하지 않고 distinct fresh run을 만드는 것이다. 일반 CLI가 resume을 지원한다는 사실이 현재 benchmark에서 사용 권한을 뜻하지 않는다.
15. Secret-safe 기록 규칙
다음 값은 tracked docs, task review, run metadata, log, metric label과 command argument에 남기지 않는다.
- IOP principal token
- raw provider credential
- private key, at-rest key, issuer/recipient private key
- slot alias와 lease id
- credential-bearing URL
- raw prompt/response, tool input/output
- caller/provider session content
허용되는 내용:
- secret file의 상대 path와 존재/mode
- route/model/stage 이름
- safe credential slot reference/revision
- hashed endpoint/config/spec identity
- redacted lifecycle 상태, duration과 usage count
- run id와 attempt identity가 필요한 controller evidence
incident evidence를 보존하기 전에 repository와 run output에서 secret 원문이 없는지 확인한다. 의심되는 artifact는 내용을 복사하지 말고 path와 redaction failure만 보고한다.
16. 실행 전 체크리스트
- 현재 manifest validation 통과
- focused/full deterministic tests fresh PASS
- benchmark runner와
../iop-s2provenance 확인 - Claude/agy/Codex command와 current version/help 확인
token/.iop-bench, CA와 provider provisioning source 존재/mode 확인; 내용 출력 없음- dev runtime source/build identity, process와 listener 확인
- managed projection, provider slot/route와 no-legacy-fallback 확인
- config observation이 runtime route/stage와 정확히 일치
- public preflight
ready=9 - 현재 plan이 exactly one scored run을 소유하고 사용자 권한이 명확함
- old run resume/retry/state edit 계획 없음
- run 이후 status, scoring, report의 run id 전달 경로 준비
17. 관련 구현
- controller/state:
scripts/agent_benchmark/attempts.py - manifest:
scripts/agent_benchmark/manifest.py - lifecycle:
scripts/agent_benchmark/lifecycle.py - workspace isolation:
scripts/agent_benchmark/workspace.py - live routing/admission:
scripts/agent_benchmark/live_iop.py - Claude adapter:
scripts/agent_benchmark/claude_iop.py - agy adapter:
scripts/agent_benchmark/agy_iop.py - Codex adapter:
scripts/agent_benchmark/codex_iop.py - measurement:
scripts/agent_benchmark/measurement.py - browser/web gate:
scripts/agent_benchmark/web_validation.py - blind scoring:
scripts/agent_benchmark/scoring.py - rubric:
scripts/agent_benchmark/rubric.py - report:
scripts/agent_benchmark/reporting.py