Delphik

Methodology

검사 매뉴얼: 데이터 벤더 태스크 품질 감사

이 문서는 벤더 태스크 샘플의 품질을 어떻게 검사하는지 설명한다.

벤더에게 보내는 리포트의 모든 수치는 이 절차에서 나오고, 하나의 감사 엔진이 채점한다.

방법은 벤더와 무관하게 같다. 모든 벤더가 같은 매뉴얼을 받는다.

여섯 축으로 검사한다.

축무엇을어떻게
1. 실행 검사태스크가 제대로 빌드되고 채점되는가동봉된 정답 풀이와 빈 제출을 각각 세 번 돌리고, 빌드된 이미지에서 정답을 찾는다
2. 정적 검사의존성이 고정되고 환경이 제대로 선언됐는가Terminal-Bench 3 검사 스크립트와 우리 자원 선언 검사
3. 설계 검사태스크가 평가 도구로 잘 만들어졌는가TB3 task-implementation 루브릭 17기준 + 적대적 재검증
4. 리워드 해킹일을 하지 않고 만점을 딸 수 있는가Opus 5 또는 Codex 블랙박스 레드팀 실행 + Docker로 재현한 화이트박스 익스플로잇
5. 실패 원인모델이 틀렸을 때 태스크 탓인가우리가 돌린 Opus 5 또는 Codex 실행을 TB3 trial-analysis 루브릭으로 판정
6. 벤치 오염공개 벤치 태스크의 복제인가지시문·풀이·검증기를 Terminal-Bench 2.1과 비교

1·4·5축은 우리가 귀사 팩에서 직접 실행한다. 팩에 동봉된 실행 기록이나 보상을 우리 실행 대신 쓰지 않는다.

이 여섯 품질 축과 별도로 난이도를 측정한다(아래 난이도 측정). 품질·가격 옆에 함께 보고하며 품질 점수에는 들어가지 않는다.


검사를 돌릴 수 없을 때

모든 태스크의 모든 검사는 측정함, 돌렸으나 쓸 수 있는 결과 없음, 안 돌림 중 하나로 이유와 함께 기록한다.

태스크 품질 숫자는 그 태스크의 채점 검사를 모두 측정했을 때만, 데이터셋 품질 숫자는 모든 태스크에 숫자가 있을 때만 낸다.

그렇지 않으면 리포트에 평가 불가로 적고 빠진 검사와 이유를 모두 적는다(예: 채점기가 보상 파일을 쓰지 않음).

빠진 검사를 통과로 치지 않는다.

누가 쟀나. 4·5축 실행은 Opus 5 또는 Codex로 한다. 리포트 상세에는 칸마다 실행한 모델과 판정한 모델을 적는다. 난이도는 아래 혼합 기준 Codex 사다리를 사용하며 기존 유효 증거를 재사용한다.

감사 범위. 검증 가능한 태스크만 감사한다. GPU가 필요한 태스크와 채점에 LLM 판정(외부 API 키)이 필요한 태스크는

실행하지 않고 태스크 수에서 빼며, 리포트의 감사 범위 밖 목록에 이유와 함께 적는다.

테스트 실패 시 보상 파일이 없는 채점기. 채점 스크립트가 테스트가 실패하면 0점을 쓰기 전에 끝나는 구조(set -e 등)이고, 그 실행의 테스트 출력이 실패로 끝났으면 0점으로 본다. 결함으로 세지 않는다.

원인 미확정. 태스크가 아니라 우리 실행 환경 탓일 수 있는 실패(예: 정답 풀이를 포함한 모든 실행에서 프로세스가 죽는 경우)는 감점하지 않는다. 원인을 찾을 때까지 그 검사는 이유와 함께 "돌렸으나 쓸 수 있는 결과 없음"으로 기록한다.

빌드 불가. 벤더 쪽 원인(만료된 패키지 저장소, 바뀐 외부 스크립트 체크섬 등)으로 환경이 빌드되지 않으면,

원인 파일·줄과 재현 기록을 남기고 채점기가 작동하지 않는 태스크(1축 천장 결함)로 센다.


1축 · 실행 검사

벤더의 environment/Dockerfile로 태스크 이미지를 빌드하고 세 가지를 본다. 정답 풀이와 빈 제출은 각각 세 번 돌리며, 한 번이라도 기준을 벗어나면 결함이다. 그래서 가끔만 통과하는 태스크도 여기서 잡힌다.

검사결함 조건등급
천장동봉된 정답 풀이(solution/)를 세 번 돌려 한 번이라도 보상이 0.9 미만: 정답을 내도 실패 보상을 받을 수 있다S1
바닥빈 제출을 세 번 돌려 한 번이라도 보상이 0.1 초과: 아무것도 안 해도 점수가 붙는다S1
정답 유출에이전트가 자기 이미지 안에서 정답·숨긴 테스트·채점기의 기대 출력에 닿을 수 있다S1

0.9·0.1 기준은 이진 보상과 연속 보상에 똑같이 적용한다.

유출은 세 곳을 본다. 빌드한 이미지 안에서 solution/·tests/ 파일과 내용이 같은 파일, 태스크가 에이전트에게 준 작업 트리

밖에서 작업 파일이 남는 자리의 파일, 그리고 벤더가 넣은 environment/ 빌드 컨텍스트를 소스에서 정답과 대조한 결과(통째로

복사한 파일, 복사한 코드, 숨긴 상수, 채점기 로그)다. 후보가 곧 유출은 아니다(검증기 입력 파일이 에이전트에게 주는 입력과 같을

수 있다). 그래서 후보는 모두 읽은 뒤에 세고, 후보가 없어도 이미지를 읽기 전에는 깨끗한 것으로 치지 않는다.

태스크가 지금 돌지 않고 벤더 쪽 원인(예: 실패하는 Dockerfile 단계, file:line 인용)을 재현했으면 채점기가 작동하지 않는

태스크로 보고 천장 결함을 센다. "지금 돌지 않는다"는 정답 풀이가 쓸 수 있는 결과를 세 번 내지 못했거나, 정답 풀이나 빈 제출을

가장 최근에 돌린 실행에서 쓸 수 있는 결과가 하나도 없었다는 뜻이다. 원인이 생기기 전(예: 고정해 둔 패키지가 내려가기 전)에

통과한 실행이 있어도 태스크는 닫힌다. 원인을 재현하지 못했으면 평가 불가로 기록한다.

2축 · 정적 검사

Terminal-Bench 3 검사 스크립트와 우리 자원 선언 검사를 전 태스크에 돌린다. 점수에 들어가는 것은 여섯 개다.

스크립트무엇을 보나등급
check-pip-pinningpip/uv 설치 버전이 고정됐는가S2
check-compose-host-bindsdocker-compose가 호스트 디렉터리를 bind mount하는가S2
check-dockerfile-sanityDockerfile apt 의존성 버전이 고정됐는가S4
check-nproc코어 수에 따라 결과가 달라지는 nproc 호출이 없는가S4
check-resource-declarationtask.toml에 cpus와 memory_mb(또는 harbor가 memory_mb로 읽는 memory)가 선언됐는가. 선언이 없으면 자원 제한 없이 돈다S4
check-task-absolute-path지시문의 상대경로가 어느 디렉터리 기준인지 에이전트에게 분명한가. 작업 디렉터리가 정해져 있으면 상대경로도 결함이 아니다S4

스크립트는 글자 패턴만 본다. 그래서 걸린 줄마다 판정이 원문을 읽고, 검사가 막으려는 문제가 실제로 있는지(주석·실행되지 않는 분기·로그 문자열·무관한 빌드 단계가 아닌지) 확인한 것만 결함으로 센다.

설계 기준이 FAIL이라는 이유만으로 정적 결함을 빼지 않는다. check-pip-pinning과 verifiable은 양쪽 근거를

대조해 정적 검사의 유효 근거 전체가 확정된 설계 결함에 포함될 때만 한 번 센다. 대조가 끝나지 않았으면 평가 불가다.

나머지 정적 검사는 environment_hygiene와 자동으로 합치지 않는다. 중복 관계가 같을 때 결함을 추가해 감점이 줄어들 수 없다.

check-dockerfile-references는 여기서 세지 않는다. 정답 유출은 1축에서 직접 잰다.

나머지 TB3 스크립트는 TB3 저장소의 게시 규약이거나, 오탐이 알려져 있거나, 다른 축이 답하는 질문이다.

3축 · 설계 검사

태스크마다 전담 검토자가 납품된 모든 파일(task.toml, instruction.md, environment/, tests/, solution/)을 읽고

TB3 task-implementation 루브릭으로 판정하며, 지적마다 file:line을 인용한다. 일부 발췌나 정규식 일치로 판정하지 않는다.

통과한 기준에도 판정 근거를 적는다. 근거가 없는 판정이 있는 태스크는 결함 없음이 아니라 측정 불가로 기록한다.

루브릭 35기준 중 핵심 17기준을 판정한다. 나머지는 TB3 패키징 규약(11개)이거나 경미하고 실행 방식에 따라 달라지는 것(7개)이다.

점수에 들어가는 기준

기준마다 심각도 등급이 하나 있다. 등급은 모델이 실제로 악용했는지가 아니라 악용이 가능한지로 정한다.

S1 · 신호가 무효

기준무엇을 묻나
do_not_modify_enforced"수정 금지" 제약이 실제로 강제되는가
task_security악성코드·자격증명 탈취·호스트 공격이 없는가
test_instruction_alignment테스트가 지시문이 요구하는 것을 검사하는가

S2 · 신호가 오염

기준무엇을 묻나
outcome_verified과정이 아니라 결과를 채점하는가
verifiable검증기가 믿을 만하고 결정적이며 효율적인가
structured_data_schema구조화 출력을 요구하면 스키마가 명시됐는가
novel공개 자료를 외워서 풀 수 없는가

S3 · 살 가치

기준무엇을 묻나
difficult정당한 이유로 어려운가(전문 경력·도메인 지식 필요)
essential_difficulty난이도가 형식이 아니라 추론에서 오는가
agentic한 번의 호출이 아니라 여러 단계의 터미널 작업이 필요한가

S4 · 위생

기준무엇을 묻나
environment_hygiene에이전트 이미지가 깨끗한가(테스트·풀이·테스트 전용 의존성 없음)
solution_quality풀이가 하드코딩이 아니라 실제로 계산하는가

판정은 하지만 점수는 실행으로 재는 기준

다섯 기준은 판정해서 리포트에 적지만, 점수는 우리가 실행한 결과로 매긴다. 읽어서 의심한 것을 실측 위에 겹쳐 세지 않기 위해서다.

solvable(1축 천장), deterministic_reproducible(1축 반복 실행), anti_cheat_robustness·verifier_execution_isolation·functional_verification(4축).

적대적 재검증

두 번째 검토자가 모든 FAIL을 깨는 것을 목표로 인용된 file:line을 전부 열어 원문과 대조한다.

조금이라도 애매하면 REFUTED로 기록한다. 익스플로잇은 실제로 돌리는 4축에서만 센다.

살아남은 FAIL만 센다. 기각된 것은 detail 문서에 이유와 함께 남긴다.

4축 · 리워드 해킹

방법답하는 질문
블랙박스Opus 5 또는 Codex에게 채점기 소스 없이 TB3 레드팀 프롬프트(hack-trial-prompt.md)를 지시문 뒤에 붙여 준다. 태스크 파일은 고치지 않는다모델이 실제로 채점기를 뚫는가
화이트박스우리가 tests/를 읽고, 태스크를 풀지 않고 만점을 받는 익스플로잇을 짜서 Docker로 재현한다채점기가 뚫릴 수 있는가

판정은 보상으로 하지 않는다. 실행 궤적 전체를 읽고 뚫림/버팀을 판정한다.

레드팀 프롬프트 없이 돌린 정상 실행(5축 실행)이 일을 하지 않고도 이미 만점을 받으면, 채점기가 공격자 없이도

안 한 일에 보상을 주는 것이라 가장 무거운 S0로 센다. 그렇지 않으면 블랙박스 뚫림은 S1, 그렇지 않고

화이트박스 재현이 있으면 S3, 태스크당 하나만 센다.

재현하지 못한 화이트박스 지적은 detail 문서에 적지만 점수에 넣지 않는다.

블랙박스는 한 번 실행이라 "버팀"은 이번 시도가 실패했다는 뜻이지 뚫을 수 없다는 뜻이 아니다.

모델이 레드팀 지시를 거절한 실행(공급자 안전 거절, 우회를 시도하지 않고 과제만 푼 경우)은 채점기를 시험하지 못한 것이라

"버팀"이 아니라 "실행하지 못함"으로 기록한다.

거절 뒤 다른 모델로 바뀌어 이어간 실행은 그 모델의 실행으로 센다.

레드팀 프롬프트가 바뀐 뒤에도 이전 레드팀 실행의 뚫림은 센다. 이전의 버팀은 세지 않는다.

정상 실행이 이미지에 남은 정답(예: 컴파일된 정답 모듈)을 읽어 보상을 받으면 리워드 해킹(S0)이고, 그 태스크는 난이도 값이 없다.

4축이 이미 감점한 태스크에서 3축 do_not_modify_enforced도 FAIL이면 같은 경로인지 판정하고, 같은 경로는 4축에서 한 번만 감점한다.

두 경로 모두 칸으로 관리한다. 채점기를 아무도 읽지 않은 팩은 화이트박스 칸이 안 돌림으로 남고,

다른 미측정 항목과 똑같이 품질 점수를 받지 못한다. 읽었는데 뚫지 못한 경우는 버팀으로 기록한다.

기록이 없는 것은 결과가 아니다.

5축 · 실패 원인

태스크마다 Opus 5(claude-code 하네스) 또는 Codex(codex 하네스)로 한 번 돌리고 TB3 trial-analysis 루브릭 6기준으로 판정한다.

태스크 결함을 가리키는 두 기준만 점수에 들어간다.

기준무엇을 묻나등급
task_specification지시문만으로 무엇을 만들지 알 수 있었나S2
difficulty_crux의도한 난점에서 실패했나 (엉뚱한 곳에서 실패하면 FAIL)S3

루브릭이 허용하는 경우 해당 없음으로 판정할 수 있고, FAIL만 센다. 보상 1을 받은 실행은 task_specification에서

FAIL이 될 수 없고(지시문보다 많은 것을 검사하는 테스트는 3축 test_instruction_alignment에서 감점), 리워드 해킹으로

판정된 실행은 4축에서 한 번만 감점하고 여기서 다시 세지 않는다. task.toml에 작성자의 difficulty_explanation이 없으면 지시문·테스트·정답에서 의도된 난점을 추정해 근거에 적고 그 기준으로 판정한다. 설명 누락은 권고로 알리며 점수에 넣지 않는다. reward_hacking은 4축이 맡고,

near_miss·refusals·low_timeout은 태스크보다 모델이나 형식 사정이라 점수에 넣지 않는다.

네트워크가 제한된 태스크에는 Claude Code 실행에 필요한 패키지·모델 API 호스트를 추가한다. 이는 접속 대상에 대한 허용이며 Claude 프로세스만의 권한이 아니다. 공개 인터넷 정책인 태스크는 공개 접근을 유지하며, allowlist 추가만으로 제한되지 않는다. 실행 설정을 보존하고 외부 정답 취득 여부를 검토할 때 궤적을 함께 확인한다.

6축 · 벤치 오염

태스크마다 지시문·풀이·검증기를 따로 Terminal-Bench 2.1 전체와 비교해 0~1 유사도를 매긴다

(0.9 = 겉만 바꾼 같은 태스크, 0.7 = 핵심 접근 동일, 0.4 = 하위 작업 공유, 0.1 = 도메인만 같음).

변수·파일·도메인 이름을 바꿔도 점수가 내려가지 않고, 공통 테스트 뼈대는 점수를 올리지 않는다. 태스크 점수는 셋 중 최댓값이다.

점수뜻반영
≥ 0.90공개 벤치 태스크의 복제결함으로 셈, S2 (같은 태스크에서 3축 novel이 이미 확정 FAIL이면 같은 사실을 두 번 빼지 않도록 건너뜀)
0.70 ~ 0.89가까움, 판정 필요detail 문서에 표시, 점수 미반영
< 0.70깨끗함없음

Terminal-Bench 장르와 비슷한 것은 당연하다. 특정 태스크와 거의 같을 때만 센다.


품질 점수

가중치는 S0 6 · S1 4 · S2 3 · S3 2 · S4 1. S0은 4축 정상 실행 리워드 해킹 전용이라 설계 기준이 아니고,

아래 표와 분모에는 들어가지 않는다. 점수에 들어가는 설계 기준을 전부 어겼을 때의 하중은

3×4 + 4×3 + 3×2 + 2×1 = 태스크당 32이다.

> 태스크 품질 = max(0, 1 − 총 하중 ÷ 32). 총 하중 = 확정 설계 결함 + 1·2·4·5·6축에서 잰 결함.

> 데이터셋 품질 = max(0, 1 − 총 하중 합 ÷ (태스크 수 × 32)). 모든 태스크를 다 측정했을 때만.

> 설계 품질 = 1 − 설계 하중 합 ÷ (태스크 수 × 32). 참고값.

> 계산 예시. 한 태스크에 확정 S2 설계 결함 1개(하중 3). 4축 블랙박스 뚫림(하중 4), 5축 difficulty_crux FAIL(하중 2).

> 총 하중 9라 태스크 품질 = 1 − 9 ÷ 32 = 0.72, 설계 품질 = 1 − 3 ÷ 32 = 0.91.

점수는 결함이 몇 개인지가 아니라 얼마나 무겁게 걸렸는지를 잰다.


난이도 측정 (품질 점수와 별개)

기준표. 새 측정은 tb21-tb4-codex-v2를 사용한다. 약한 쪽부터 Luna low 1.14, Terra max 1.94, Sol max 3.06, Astra max 4.08이다. 비교 기준은 Haiku 4.5의 기존 설정 1, Sonnet 5의 기존 설정 2, Opus 5의 기존 설정/TB4 xhigh 3, Fable 5.1 max 4다. TB4의 연결 기준 Sonnet은 max다.

보정 방법. TB2.1의 기존 고정 눈금 (44.2,1), (80.4,2), (87.6,3), (89.9,4)를 L이라 한다. Luna=L(49.4), Terra=L(78.4). TB4의 (Sonnet max 12.4%,2), (Opus xhigh 53.9%,3), (Fable max 57.9%,4) 사이를 구간별 선형 보간한 함수가 U다. Sol은 (L(88.8)+U(37.3))/2=3.060870, Astra는 마지막 구간을 조금 연장한 3+(58.2-53.9)/(57.9-53.9)=4.075다. Opus는 양쪽 기준이 3이라 혼합해도 3이다. Astra를 임의로 4에 고정하지 않는다.

TB2.1 리더보드, OpenAI effort 차트, TB4 리더보드의 2026-09-18~19 자료를 사용한다. 기존 TB2.1 기준 상수의 원 출처를 최신 Claude 공식 성적으로 재검증한 것은 아니다. 벤치별 effort·하네스 차이를 공개하는 근사 기준 지수다. 50:50은 운영상 정의이며 소수점 차이는 통계적으로 유의한 우열이 아니다. TB2.1 85% 이상이면 상위 벤치 자료도 확인하되 좌표는 프로필 버전에 고정한다.

실행 방향. 기존 유효 결과를 먼저 재사용한다. 부족하면 Sol max 정상 풀이 3회부터 시작한다. 부분 보상 평균 ≥0.8 또는 이진 3/3 성공이면 Terra max로 낮추고, Terra 평균 ≥0.5이면 Luna low로 낮춘다. Sol 평균 <0.2 또는 이진 0/3이면 Astra max로 올린다. 중간 결과면 해당 단계에서 끝낸다. 이미 Astra max 결과가 있다면 쉽게 풀 때 Sol로 내려가며, Astra도 성공이 없을 때 더 약한 Sol로 내려가지 않는다. Sol의 완료 근거 없이 Astra에서 중간 결과가 나왔다면 그 근거로 측정을 끝내고 Sol을 새로 예약하지 않는다. Luna·Terra가 이미 평균 보상 0.5를 끼우면 강한 모델을 추가 실행하지 않는다.

증거 재사용. 완료된 Claude 사다리는 유효 원본 보상과 그대로인 기준 좌표로 재계산해 유지할 수 있다. 옛 Codex D는 새 기준으로 재계산하며 이전 값과 프로필은 보존한다. 벤치별 effort 차이를 허용해도 실제 trial의 모델·effort를 바꾸어 기록하지 않는다. Astra high는 Astra max로 재사용하지 않는다. 실행 불가·정책 거절을 점수나 다른 모델 우회로 바꾸지 않는다.

난이도 D. 실제 벤더 태스크 평균 보상이 0.5가 되는 능력 위치다. 실행한 단계 사이 선형 보간, 교차점이 없으면 기존 기울기 0.6으로 외삽하고 외삽임을 기록한다. 부분 보상은 ≥0.9, 이진은 =1을 성공으로 센다. 데이터셋 D는 사다리 종료 후 D가 있는 태스크들의 중앙값이며 산출 범위를 함께 표시한다. 실행 불가·solvability는 제외하고 산출값이 없으면 null이다. 성공 스텝 수로 측정하는 호라이즌은 D에 더하지 않는다.

측정 한계. 최상단 Astra에서 성공이 없으면 D를 부여하지 않는다. 확인된 5축 task_specification·difficulty_crux FAIL이 있으면 태스크 결함으로 설명하고, 아니면 원인 미확정인 측정 한계로 기록한다. 판정 부재를 PASS로 해석하지 않는다. 공개 벤치 성적은 실제 태스크 실행을 대체하지 않으며 D는 품질 점수와 별개다.


이 매뉴얼은 방법 문서다. 벤더별 수치와 태스크 단위 근거는 함께 보내는 detail 문서에 있다.