ARC-AGI-3 Research Note R1: 한 수의 값, 그리고 program-as-policy (KR)
ARC-AGI-3 Research Note R1: 한 수의 값, 그리고 program-as-policy — 설계에서 첫 실측까지
연구 노트입니다. 워킹노트(1·2편)가 제출과 실측의 기록이라면, R 시리즈는 판을 바꿀 만한 아이디어를 공부하고 설계하고 검증하는 과정의 기록입니다. 이 글은 하나의 질문을 끝까지 따라갑니다 — 왜 지금 패러다임의 개선은 멈추는가, 그리고 한 수에 드는 토큰을 자릿수로 줄이는 구조는 무엇인가. 우리 로그의 측정에서 출발해, 공개셋을 사실상 정복한 두 시스템(EWM, Schema)의 코드와 트레이스를 뜯고, 우리 제약(로컬 27B, 채점 런당 ~5.8만 토큰)에 맞는 이식을 설계한 뒤, 그 설계의 첫 파일럿(P0) 실측 결과까지 담았습니다. 모두 2026년 8월 5일 기준입니다.
이전 글: 워킹노트 2편
0. 잔손질의 상한은 어디였나
2편의 결론은 “점수판이 아니라 시스템을 읽어야 했다”였고, 그 독해가 가리킨 개선들 — 기억 채널 복구, 실험 원장, 클론 간 전이 — 은 전부 구현되어 검증을 마쳤습니다. 그런데 이 개선들에는 공통의 천장이 있습니다. 전부 기존 비용 구조 안의 수리라는 것. 현 패러다임에서 LLM은 매 턴 루프 안에 있고, 관찰을 읽고 액션을 고르는 데 턴마다 수백 토큰을 씁니다. 낭비를 아무리 줄여도 “레벨 하나를 이해하는 데 드는 토큰”의 자릿수는 그대로입니다.
(이 천장은 이 글 부록의 compaction A/B에서 한 번 더 실측으로 확인됩니다 — 기억 장치가 완벽히 작동해도 분포는 움직이지 않았습니다.)
1. 한 수의 값 — 우리 에이전트는 한 수에 얼마를 쓰나
56런짜리 대회 시뮬레이션의 트랜스크립트 2,982턴을 전수 분석했습니다. LLM 턴 하나가 실제로 몇 개의 액션을 실행하는지의 분포입니다.
| 턴당 실행 액션 | 비율 |
|---|---|
| 0개 (생각만 하고 행동 없음) | 28% |
| 1개 | 43% |
| 2–4개 | 15% |
| 5–9개 | 9% |
| 10개 이상 | 4% |
중앙값 1, 평균 2.06, 런당 중앙값 52턴, 액션당 토큰 중앙값 600. 우리 에이전트는 턴의 71%에서 한 걸음 이하를 걷고, 걸음 하나에 600토큰을 냅니다. 런당 예산 ~5.8만 토큰에서 걸음 수가 ~100으로 고정되는 구조입니다. 압축이니 원장이니 하는 것들은 저 600을 500으로 만드는 일이고, 필요한 건 저 분포 자체를 오른쪽으로 옮기는 일입니다.
2. 정독 결과 ①: EWM — 검증이 본체, 시뮬레이터는 껍데기
공개셋 58.12%(GPT-5.5, 25게임 중 15게임 완주)를 기록한 Executable World Models의 공개 저장소를 통째로 읽었습니다. 핵심 구조는 넷입니다.
- 컨트롤러에 LLM이 없습니다. 순수 파이썬 상태기계가 세션 로그를 읽고 상황(게임오버/새 레벨/진전 없음)에 맞는 프롬프트 프로토콜을 고릅니다. 탐색→모델→검증→계획의 사이클은 컨트롤러 단계가 아니라 한 번의 긴 에이전트 턴 안에서 프롬프트 규율로 강제됩니다.
- 고정 인터페이스 4개. 엔진
world_model_engine(state, action) → (new_state, status), 초기상태 재구성, 렌더러, 플래너 — 빈 스텁을 주고 LLM이 채웁니다. 보상 함수는 어디에도 없습니다. - 검증은 전 이력 정확 재생입니다. 기록된 모든 시도의 모든 스텝을 모델로 재생해 렌더링 프레임이 관측과 정확히 일치해야 합니다. 불일치는 차단 이벤트입니다.
- 플랜은 실행 전에 모델 안에서 증명됩니다. 실행기는 매 액션을 예측과 대조하며 어긋나면 즉시 멈춥니다.
그리고 후속 ablation 논문에 이 방향의 가장 중요한 반전이 있습니다. 검증 없는 실행형 모델은 순수 텍스트 world model보다 오히려 못합니다 (51.16% vs 58.85%). 고정 인터페이스 + 정확 재생 검증을 붙이는 순간 65.6%, 판올림을 거치면 82%까지 뜁니다. 이식해야 할 본체는 “파이썬 시뮬레이터를 쓰게 하자”가 아니라 “모델의 예측을 기록된 전이 전체와 기계적으로 대조하게 하자”입니다.
3. 정독 결과 ②: Schema 트레이스 — 99%짜리 플레이의 실물
Schema 팀이 공개한 트레이스 데이터셋에서 난이도별 4개 궤적을 해부했습니다 (25게임 × 2모델, 자가보고 98.98%/95.35% — 채점기가 동봉되어 로컬 재검산이 가능했습니다).
- 계약은 3함수뿐:
init_state(entry_grid)/predict(state, grid, action, x, y) → (next_grid, info, next_state)/is_goal(grid). - notes.md가 매 턴 프롬프트에 통째로 재주입 — 컨텍스트가 아니라 외부 메모리가 기억의 본체입니다.
run_backtest: 기록된 전이 전부를 predict에 통과시켜 불일치를 보고. 에이전트들은 “backtest 10/10 green”을 확인한 뒤에야 긴 플랜을 커밋합니다.commit_actions는 배치 플랜을 제출하고, 하네스가 한 스텝씩 예측과 대조 — 어긋나는 순간 나머지 플랜을 폐기합니다. 긴 개방루프 배치를 안전하게 만드는 건 이 surprise 게이트입니다.
핵심은 비용 구조입니다. 실측값입니다.
| 궤적 | LLM 턴 | 액션 | 액션/턴 | 토큰(대략) |
|---|---|---|---|---|
| ft09 (쉬움, 100%) | 15 | 78 | 5.2 | ~6.0만 |
| sb26 (중간, 98.6%) | 12 | 135 | 11.2 | ~5.6만 |
| dc22 (어려움, 98.7%) | 218 | 1,205 | 5.5 | ~63만 |
턴당 3~11액션 — 우리의 중앙값 1과 자릿수가 다릅니다. 그리고 쉬운·중간 게임은 프런티어 모델 기준으로도 ~6만 토큰 안에서 끝납니다. 우리의 런당 예산과 같은 자리입니다.
4. 이식 설계: 우리 제약에서의 D1
| 부품 | Schema/EWM | 우리 현재 | 필요한 공사 |
|---|---|---|---|
| 모델 코드의 영속 | 파일 시스템 | 샌드박스에 파일 IO 없음 | 하네스측 world-model 저장소 + 콜마다 재주입 |
| 전이 기록 | 이벤트 로그 | transitions 변수 이미 주입됨 | 없음 — backtest는 샌드박스 안에서 가능 |
| 배치+surprise 게이트 | commit_actions | action(list) + 혼합배치 중단 그래프트 | 거의 동형 — 프로토콜만 |
| 모델 위 탐색 | run_bfs 도구 | stdlib로 in-sandbox BFS 가능 | 프롬프트만 |
| 결정론 | 가정 | 35.5% 반복쌍 발산 실측 | settled-frame 대조 + 오차 허용 + “시뮬 불가” 가족 플래그 |
최소 이식안(v0): ① 게임당 {src, notes}를 하네스가 보관하고 매 콜 주입 — 구현은 부모측 코드 재작성입니다. def predict(가 든 코드 셀을 자동 캡처해 두고, 이후 모든 셀 앞에 world_model_src 문자열로 주입하면 모델이 exec(world_model_src)로 복원합니다. 샌드박스 프로토콜은 건드리지 않습니다. ② 프롬프트를 model-first 규율로 전환(탐침 스윕 → predict 작성 → 전이 전체 backtest → predict 위 탐색 → 플랜 일괄 방출), ③ 불일치율 20% 초과 가족은 “시뮬 불가”로 표시하고 현행 모드로 폴백 — EWM의 결정론 가정을 우리의 35.5% 실측에 맞게 접는 부분입니다.
출력 형식의 신뢰성 문제도 조사 중에 답이 나왔습니다. 우리 서빙 스택(vLLM 0.19 계열 — 조사 중 wheelhouse 버전 표기가 정정됐습니다)은 서버 플래그 없이 요청 단위 구조화 출력을 지원합니다. 다만 문헌 근거(Tam et al. 2024의 “형식 제약은 추론을 깎는다” + projection-tax 후속들)에 따라: 플랜 JSON에는 스키마 제약, 파이썬 world model에는 절대 금지 — 코드는 assistant 프리필과 stop 토큰으로 진입만 강제하고 ast.parse 수리 루프로 처리합니다.
5. P0 파일럿: 설계와 실측
설계를 그래프트로 구현해 곧바로 파일럿을 돌렸습니다. 공개 게임 4개 — 결정론 쌍(bp35, tn36)과 비결정 쌍(m0r0, sk48) — 를 세 조건으로 동시에: 총 12런, 게임 ID 접미사로 에이전트를 태깅했습니다.
| 조건 | 내용 |
|---|---|
| baseline | 현행 스택 그대로 (대조군) |
| protocol | MODEL-FIRST 프롬프트만 추가 |
| full | protocol + world-model 저장소 |
주의: 12런 병렬은 채점 환경(28런 병렬)보다 토큰이 두 배쯤 넉넉합니다(런당 ~12만 토큰). P0는 “할 수 있는가”를 묻는 파일럿입니다.
결과
정정 (2026-08-06). 이 절의 첫 판에는 “protocol/full 조건에서 predict 작성 4/4, backtest 4/4”라는 수치가 있었습니다. 이것은 측정 오류였습니다 — 프로토콜 블록 자체가 매 턴 트랜스크립트에 인쇄되므로, 문자열 검색이 프롬프트가 찍어 놓은 글자를 모델의 행동으로 오인한 것입니다. 행 시작 앵커(
^def predict()로 다시 재면 모델이 실제로 predict를 작성한 런은 P0 전체에서 0건입니다. 아래는 정정된 수치와 해석입니다.
| 조건 | L1 클리어 | 액션/턴 (med / p90) | 토큰/액션 | predict 실제 작성 (정정) |
|---|---|---|---|---|
| baseline | 2/4 | 1 / 6 | 641 | 0/4 |
| protocol | 2/4 | 2 / 13 | 415 | 0/4 |
| full | 3/4 | 1 / 6 | 755 | 0/4 |
관찰 ① (정정) — 관문은 통과되지 않았습니다. 모델은 프로토콜에서 값싼 부분만 골라서 따릅니다: 탐침 스윕과 액션 묶어 보내기는 하고(관찰 ②의 실체), 헬퍼 함수도 풍부하게 쓰지만(행 앵커 기준 32/56 파일에 def find_node, def get_progress 류), 비싼 핵심 — 전방 다이내믹스 predict를 쓰고 backtest하는 것 — 은 건너뜁니다. 매 턴 눈앞의 유인이 “일단 움직이자”인 이상, 여러 턴에 걸친 비싼 작업은 말로 시켜서는 나오지 않는다는 뜻입니다.
관찰 ② — 비용이 내려간 것 자체는 실측입니다. protocol 조건의 641→415 토큰/액션(−35%), p90 6→13은 행동 지표라 오염과 무관합니다. 다만 그 출처는 model-building이 아니라, 액션을 묶어 보내라는 프로토콜의 압박이었습니다.
관찰 ③ — m0r0 클리어도 실측이나, 귀속은 불확실해졌습니다. predict 없이 나온 클리어이므로, 스윕의 체계성 덕인지 소음(n=1)인지 가릴 수 없습니다.
L2는 여전히 어느 조건에서도 0이고, 조건당 n=4입니다.
6. 부록: compaction A/B는 중립이었다
같은 기간에 끝난 56런 A/B(무압축 vs 압축 — 축출 대신 실험 원장·레벨 응축을 넣은 버전)의 판정도 기록합니다. 장치는 완벽 작동했습니다 — 원장이 56/56 트랜스크립트에 주입, “repeatedly inert” 경고 99회, 레벨 전환 응축 8회. 그러나:
| 무압축 | 압축 | |
|---|---|---|
| L1 (웨이브1/2) | 46% / 57% | 50% / 61% |
| L2+ | 3+3 | 1+2 |
| 총 클리어 레벨 | 35 | 34 |
+4pp는 소음 범위, 총량 동일. 기억을 보존해도 그 지식이 예산 안에서 클리어로 전환되지 않는다 — 0장의 명제(“패러다임 안 수리는 분포를 못 움직인다”)의 세 번째 실측 확인이자, P0를 돌린 이유의 재확인입니다.
7. 나머지 갈래의 상태
- D2 (오프라인 증류): 실현성 조사 완료. bf16 베이스에 LoRA → 병합 → FP8 재양자화(~28GB, 우리 스택이 그대로 로드). 재료는 Schema 트레이스(~8–20M SFT 토큰 추정), 계산 비용은 H100 4–10시간·수십 달러. 진짜 비용은 파이프라인과 검증으로 2–4주짜리 — 프롬프트 측이 한계에 닿은 뒤의 후속 베팅.
- D3 (토큰 0 탐침): “Explore Before You Solve”에서 예산 공식 $B_{\max} = \max(5, \min(30, 0.4\,h_1))$ (우리 예산이면 탐침 ~30, 검증 1–3, 나머지 풀이)과, 그들의 실패에서 나온 처방 — LLM 프라이어에 탐색을 맡겼다가 원클릭 게임 4개를 전패 → 결정론적 오프닝 스윕(~10액션) 하드코딩 — 을 가져와 D1 탐침 단계에 흡수.
- D4 (관측 압축): Schema의 hex 행 인코딩(~1.3천 토큰/프레임)이 참고점. D1에 부분 흡수.
- D5 (클론 × 프로그램): 정찰조의 발행물을 액션 세그먼트에서 world-model 소스로 승격 — 검증된 전이 인프라 위에 그대로. D1이 서면 거의 공짜.
8. P1 결과, 그리고 갈림길
P1(56런 대회 시뮬, 채점 환경의 ~5.8만 토큰, program mode 전면 가동)까지 마친 결과를 요약합니다. 규율의 값싼 부분(스윕과 묶어 보내기)은 이번에도 지켰지만, P0에서 봤던 비용 개선은 토큰 기근에서 사라졌고(토큰/액션 562→544, 턴당 액션 분포 동일), 결과 분포도 평평했습니다(L1 웨이브별 50/46% vs 대조군 50/61%, 총 클리어 30 vs 34). predict 작성은 56런 중 1건.
정정된 그림에서 교훈은 EWM 정독(§2)으로 되돌아갑니다. EWM이 작동한 것은 프롬프트가 훌륭해서가 아니라 스크립트 컨트롤러가 단계를 기계적으로 강제했기 때문입니다. 권고는 장식이었고, 강제가 본체였습니다. 우리의 다음 갈림길은 둘입니다:
- 기계적 강제 (P1b) — 하네스 수준에서 값싼 경로를 막는 것. 예: 게임 초반 N턴 이후에는 저장소에 predict가 없으면(그리고 sim-free 선언도 없으면)
action()이 “모델부터 작성하라”는 안내와 함께 거부. 골격 predict(항등함수 + TODO)를 저장소에 미리 심어 “확장이 무시보다 싸게” 만드는 시딩과 결합. - 증류 (D2) — 프롬프트로 안 되는 행동은 가중치로 심는 것. 조사가 끝나 있는 2–4주짜리 베팅(§7)이며, “프롬프트 저항”이야말로 SFT가 고치는 종류의 문제입니다.
어느 쪽이든, 이 시리즈의 방법론적 교훈 하나는 이미 확정입니다: “지시를 따랐는가”는 프롬프트가 찍어 놓은 글자와 분리해서 재라. 문자열이 트랜스크립트에 있다는 것과 모델이 그 행동을 했다는 것은 다른 명제입니다.
Sources
- EWM 공개 코드 · 논문 · ablation 후속
- Schema 트레이스 데이터셋 (자가보고, ARC Prize 미검증)
- Explore Before You Solve · Tycho · Tam et al.
- 우리 측정: 56런 시뮬 트랜스크립트 2,982턴 / P0 12런 3암 커밋 / 56런 compaction A/B (2026-08-05)