OpenCode hybrid 실패를 IOP 코드 결함으로 오인하지 않도록 ornith-fast Node 비가용과 복구 후 통과 근거를 남기고, direct 재검증의 표준 배포 차단 상태를 분리한다.
7.8 KiB
IOP 벤치 경로 최소 HTML 스모크
목적
벤치 대상 9개 caller/model/route 조합에 같은 최소 index.html 생성 요청을 한 번씩 직접 보내 호출 경로만 빠르게 확인한다. 전용 runner, manifest, 자동 retry, browser gate와 품질 채점은 사용하지 않는다.
고정 요청
외부 asset과 JavaScript 없이 단일 index.html을 구현한다. 문서에는 <!doctype html>, <title>IOP Route Smoke</title>, <h1>IOP_ROUTE_SMOKE_OK</h1>이 정확히 한 번씩 있어야 한다. direct 경로는 빈 caller workspace의 파일을 확인한다. Edge-owned execution preset은 비공개 workspace가 완료 전에 정리되는 제품 계약을 따르므로 caller 로컬 파일이 아니라 terminal decision.output의 완료·marker를 확인한다.
사전 확인 — 2026-08-13
| 항목 | 결과 |
|---|---|
| Claude Code | 실제 원격 실행기 2.1.177 확인 |
| OpenCode | 현재 workspace 1.18.3 확인; command-scoped provider config 사용 |
| Codex | 실제 원격 실행기 0.146.0 확인 |
| managed CA | live Edge CA bundle 확인 |
| principal token | 원격 SOPS의 기존 두 token 사용; 별도 benchmark token 미사용 |
public /v1/models |
두 기존 token 모두 HTTP 200, route 9개 확인 |
| ambient CA override | 호출 전후 unset 확인 |
경로 결과
| 경로 | 최초 1회 결과 | 재검증 | 분류 |
|---|---|---|---|
| Claude Code → Claude direct | 통과 | 없음 | 기존 성공 |
| Claude Code → Gemini direct | 통과 | 없음 | 기존 성공 |
| OpenCode → Gemini direct | 6초, 첫 glob tool 성공 뒤 두 번째 provider 호출 HTTP 400 |
provider normalization 구현·dev 반영 완료; live 배포 뒤 재검증 대기 |
선택된 Gemini Chat profile의 thought_signature를 표준 caller history로 왕복하지 못한 IOP 결함; agy는 구현 Agent 부적합으로 대상 제외 |
| Claude Code → GPT direct | provider HTTP 400 | operation normalization 반영 뒤 9초, caller success, index.html marker 1회 |
IOP가 tools+effort를 Chat으로 보낸 결함 수정 확인 |
| Codex → GPT direct | 30초, turn.failed, 파일 없음 |
공식 설정대로 임시 CODEX_HOME, Responses 전용 provider, CODEX_CA_CERTIFICATE에 CA bundle을 사용해 10초 통과 |
측정 환경 결함: 첫 호출은 CA bundle 대신 Edge leaf 인증서를 사용 |
| Claude Code → Gemini execution preset | 184초, caller terminal success, caller workspace 파일 없음 | 새 배포에서 33초 caller 정상 종료; Plan/Work/Review, workspace write/read/list, artifact 3개 cleanup 성공 | default-selector dispatch 결함 해소; terminal 문구에 marker가 없는 것은 caller-visible 결과 판정과 분리 |
| OpenCode → Gemini execution preset | 7초, Plan 통과 후 Work provider 오류 |
ornith-fast Node를 명시적 Up 복구한 뒤 19초, caller terminal marker 1회, 오류 0 |
preset은 ornith-fast → RTX provider로 정상 라우팅됐으나 해당 Node가 내려가 Edge가 502 provider unavailable로 닫은 환경 결함; OpenCode·IOP 코드 결함 아님 |
| Claude Code → GPT execution preset | 미실행 | selector/Chat 응답 정규화 배포 뒤 최신 Claude 요청이 provider 전 95ms에 messages[1].role 검증 거절 |
실제 caller가 user → system과 mid-conversation-system beta를 보냄; IOP가 beta만 선언하고 ingress/lineage/Chat/Responses normalize를 구현하지 않은 별도 제품 결함 확인·국소 수정 |
| Codex → GPT execution preset | 16초, turn.completed, terminal marker 1회 |
없음 | 통과 |
추가 API 분리에서는 동일 principal의 최소 /v1/responses가 HTTP 200이었다. Codex direct도 사용자 설정과 로그인 상태를 배제한 임시 CODEX_HOME, Responses 전용 custom provider, 원격 SOPS의 기존 token, command-scoped managed CA bundle으로 통과했다. OpenCode direct는 command-scoped OPENCODE_CONFIG_CONTENT와 원격 SOPS의 기존 token을 사용해 user config를 변경하지 않았다. 첫 glob tool까지 성공했으나 caller가 Gemini provider extension을 표준 Chat history에 보존하지 않아 다음 요청이 thought_signature 누락 HTTP 400으로 실패했다. 이는 OpenCode 전용 문제가 아니라 selected Gemini Chat provider normalization 누락으로 분류했다.
두 preset 최초 실패는 provider 자체 실패가 아니었다. 코드 대조에서 default resource selector가 의도적으로 빈 provider ID를 동결하는 반면 사후 검증은 pool이 정상 선택한 실제 provider ID와 무조건 같아야 한다고 요구한 결함을 확인했다. explicit selector의 provider ID와 profile/model/credential/path fence는 유지하고, default selector만 pool 선택을 인정했다. 재배포 뒤 Gemini preset은 전체 stage와 workspace lifecycle이 통과했다. GPT preset은 다음 경계까지 진행해 실제 OpenAI Chat 응답의 service_tier, system_fingerprint, annotations, null refusal을 private strict decoder가 거부하는 별도 normalize 누락을 드러냈다. 공통 provider-normalization 계층에서 Chat/Responses 결과를 같은 canonical stage envelope로 수렴시키는 국소 회귀가 통과했다.
그 수정 배포 뒤 최신 Claude Code는 첫 task 요청에 messages=[user, system]과 mid-conversation-system-2026-04-07 beta를 보냈다. IOP는 beta header를 지원 목록에 두었지만 strict ingress와 logical-request lineage는 여전히 user/assistant만 허용했고, Chat/Responses bridge에도 system message 변환이 없었다. system 내용을 user text로 낮추지 않고 ordered privileged message로 보존하도록 공통 Anthropic 입력 normalize 경계를 수정했으며, 첫-position system, assistant 뒤 system, system 뒤 user, non-text system, 미완료 tool 결과 사이 삽입은 fail-closed로 유지했다.
해당 입력 normalize 배포 뒤 단일 재검증은 Plan 성공 후 Work validation으로 종료됐다. preset 구성상 Plan/Review는 GPT지만 Work는 ornith-fast다. RTX Ornith에 같은 forced workspace tool shape를 직접 보낸 결과 native tool_calls가 정상 반환됐고, 응답의 top-level provider timings가 기존 Work codec에서는 허용되지만 새 공통 Chat normalize allowlist에서 빠져 있음을 확인했다. 공통 normalize가 timings를 검증 후 폐기하도록 보완했다.
OpenCode → Gemini execution preset의 최초 실행은 Plan을 정상 통과했지만 Work에서 7초 만에 provider 오류로 닫혔다. live preset과 Edge 단계 지표를 대조한 결과 Work는 ornith:35b가 아니라 의도한 ornith-fast로 선택됐으며, 동일 Work request shape의 단일 직접 호출은 연결된 Node에 해당 provider가 없어 HTTP 502 provider unavailable를 반환했다. 사용자 관리형 RTX runtime을 toggle가 아닌 명시적 Up으로 복구한 뒤 실패 경로만 1회 재검증했고, 19초 내 caller terminal marker 1회·오류 0으로 통과했다. preset workspace가 caller 로컬에 파일을 남기지 않은 것은 기존 정리 계약과 일치한다.
재개 조건
Gemini Chat tool-call normalization 코드는 dev commit d99305d1과 merge dc2d9968로 반영됐다. 현재 live dev는 이전 release를 실행 중이며, 원격에 이전부터 미종료 release branch 두 건이 남아 표준 dev-runtime-deploy가 새 release를 시작하지 않고 fail-closed했다. 해당 Git release 상태를 별도로 정리한 뒤 표준 배포를 수행하고 OpenCode → Gemini direct 실패 경로만 1회 재검증한다. OpenCode → Gemini execution preset은 이미 통과했으므로 반복하지 않는다. 제품 전체 capacity gate나 unrelated 운영 라우트는 이 얇은 경로 검증의 판정 기준으로 섞지 않는다.
성공한 경로는 반복하지 않는다. 실패한 경로는 원인이 변경된 경우에만 해당 경로를 1회 재검증한다.