Interlock · Experiment E9실험 E9

Prevent it, or merge and fix it afterwards?미리 막을까, 합친 뒤 고칠까

A common answer to conflicts between agents is to merge, run CI, and let another agent fix whatever breaks. E9 tests that against Interlock, and judges the end result with a hidden check the agents never see, not with git. 에이전트 간 충돌에 대한 흔한 답은 "병합하고 CI를 돌려서, 깨진 건 다른 에이전트에게 고치게 하라"입니다. E9는 이 방식을 Interlock과 비교하고, 최종 결과를 git이 아니라 에이전트가 보지 못하는 숨은 검사로 판정합니다.

Run on 2026-10-20 with Interlock V3.2.0 and real Claude Code 2.1.303 sessions on Sonnet 5.5: 20 runs, 43 sessions, $3.53 reported cost.2026-10-20, Interlock V3.2.0과 실제 Claude Code 2.1.303 세션(Sonnet 5.5)으로 실행. 시행 20번, 세션 43개, 보고 비용 $3.53. Raw results (JSON)원자료 (JSON)

Method방법

  • Two real agents work at the same time, each in its own worktree:실제 에이전트 둘이 각자 worktree에서 동시에 일합니다.
    • A changes login to take a one-time code (otp) and updates its caller reorder.A: login이 일회용 코드(otp)를 받도록 바꾸고, 호출하는 reorder도 고칩니다.
    • B adds checkout(), which calls login.B: login을 부르는 checkout()을 추가합니다.
  • Merge, then fix: both branches merge into main and CI (pytest) runs. If CI is red, a third agent is asked to make the tests pass without undoing either branch's intent, up to two rounds. This is how a merge queue, or "let the agent fix it", works.합친 뒤 고치기: 두 브랜치를 main에 병합하고 CI(pytest)를 돌립니다. CI가 빨간색이면 세 번째 에이전트에게 "두 브랜치의 의도는 되돌리지 말고 테스트가 통과하게 고치라"고 맡깁니다(최대 2번). 병합 대기열이나 "에이전트가 고치게 두는" 운영 방식을 흉내 낸 것입니다.
  • Variants: tested, where B is also asked to write a test for checkout, so CI has a chance to see the break; untested, with only the existing tests.변형: tested는 B에게 checkout 테스트도 쓰게 해 CI가 깨짐을 볼 기회가 있고, untested는 기존 테스트만 있습니다.
  • Conditions: no Interlock (merge, then fix) and Interlock (the setup interlock init installs). Five runs per variant and condition.조건: Interlock 없음(합친 뒤 고침)과 Interlock(interlock init과 같은 설정). 변형×조건마다 5회.
  • Hidden check on the final main. It counts as correct only if all three hold: checkout works when given an otp; every login call fits its definition; login still requires an otp and rejects an empty one.숨은 검사로 최종 main을 판정합니다. 세 가지가 모두 참이어야 올바름입니다. otp를 넘기면 checkout이 동작한다. 모든 login 호출이 정의에 맞는다. login이 여전히 otp를 요구하고 빈 값을 거부한다.

Results결과

Variant · condition변형 · 조건 CI green at first merge첫 병합에서 CI 통과 Fix rounds고친 횟수 main correct at the end끝에 main이 올바름 login still requires otplogin이 otp를 계속 요구 Cost per run시행당 비용 Time per run시행당 시간
tested · no Interlocktested · Interlock 없음3/522/55/5$0.16323 s
tested · Interlock4/515/55/5$0.22132 s
untested · no Interlockuntested · Interlock 없음5/500/55/5$0.11614 s
untested · Interlock5/505/55/5$0.20626 s
  • Merge-then-fix only works when CI sees the break."합친 뒤 고친다"는 CI가 깨짐을 볼 때만 작동합니다.
    • untested: CI was green in 5 of 5 runs and main was broken in 5 of 5: calling checkout raises a TypeError. Nothing ever asked for a fix.untested: CI는 5번 모두 초록색이었고 main은 5번 모두 깨져 있었습니다. checkout을 부르면 TypeError가 납니다. 고칠 기회 자체가 없었습니다.
    • tested: the 3 runs where CI was green were all broken. In each, B's test had replaced login with a monkeypatch, so the test never saw the real signature. The 2 red runs were fixed correctly in one round.tested: CI가 초록색이던 3번은 모두 깨져 있었습니다. 세 번 모두 B의 테스트가 login을 monkeypatch로 바꿔 놓아 실제 시그니처를 보지 못했습니다. 빨간색이던 2번은 고치는 에이전트가 한 번에 올바르게 고쳤습니다.
  • Without Interlock, main ended correct in 2 of 10 runs, and CI was green in all 8 broken ones. With Interlock, 10 of 10 (Fisher's exact test, two-sided p ≈ 0.0007).Interlock 없이는 main이 10번 중 2번만 올바르게 끝났고, 깨진 8번은 모두 CI가 초록색이었습니다. Interlock은 10번 모두 올바랐습니다(Fisher 정확 검정, 양측 p ≈ 0.0007).
  • With Interlock, B's first edit was refused in 7 runs, and B rewrote the call to the new signature every time. In one run B gave checkout's otp parameter a default of None and wrote a test that called it without one; CI went red and the fixing agent fixed it in one round.Interlock에서는 B의 첫 편집이 7번 거부됐고, 7번 모두 B가 새 시그니처에 맞춰 다시 썼습니다. 한 번은 B가 checkout의 otp 인자 기본값을 None으로 두고 otp 없이 부르는 테스트를 써서 CI가 빨간색이 됐고, 고치는 에이전트가 한 번에 고쳤습니다.
  • No fixing agent gave up the intent, for example by making otp optional.고치는 에이전트가 의도를 버린 경우(예: otp를 선택 인자로 만들기)는 없었습니다.

What to watch주의할 점

  • Interlock costs more per run: $0.06 to $0.09 (36% to 78%) and 9 to 12 seconds. Most of the cheap runs without Interlock were the ones that left main broken.Interlock은 시행당 더 듭니다: $0.06~0.09(36~78%), 9~12초. Interlock 없이 싸게 끝난 시행은 대부분 깨진 main을 남긴 시행입니다.
  • untested is the worst case for merge-then-fix: a new call with no test of its own. But even in tested, 3 of 5 ended broken because the test was mocked.untested는 "합친 뒤 고치기"에 가장 불리한 경우입니다(자기 테스트가 없는 새 호출). 다만 tested에서도 가짜 테스트 때문에 5번 중 3번이 같은 결과였습니다.

Limits한계

  • One scenario and five runs per cell. One model (Sonnet 5.5).시나리오 하나, 칸마다 5회. 모델 하나(Sonnet 5.5).
  • The fixing agent did not use a shell. Had it run the tests itself, more tested runs might have ended correct.고치는 에이전트는 셸을 쓰지 않았습니다. 테스트를 직접 돌려 볼 수 있었다면 tested에서 올바른 비율이 더 높았을 수 있습니다.
  • We designed the tasks and the hidden check, and no one else has reproduced the results. The Interlock source and the experiment harness are not public.작업과 숨은 검사는 우리가 설계했고, 다른 사람이 재현한 적은 없습니다. Interlock 소스와 실험 도구는 공개하지 않습니다.