스텁을 발견한 그 토요일
에이전트는 컴파일되고 CI를 통과하지만 아무것도 하지 않는 코드를 출시할 것이다. 데모할 수 있는 엔진과 파트너가 그 위에 개발할 수 있는 런타임의 차이는, 스텁이 문제를 일으키기 전에 그것을 찾아내는 규율이다.
오늘은 원래 테스트를 작성하는 날이어야 했다.
이런 문장을 쓰게 될 줄은 몰랐다. 계획은 런타임이 지금 노출하는 C API를 가져다가, 그것에 대해 진지한 단위 테스트 스위트를 작성하고, 커버리지 수치가 올라가는 것을 지켜보고, 이 엔진이 더 이상 “감으로 에이전트가 코딩한 것”이 아니라 “테스트로 검증된 에이전트 코딩”이라는 일종의 전문가적 자부심을 느끼는 것이었다.
그 계획은 두 시간 정도 버텼다.
내가 발견한 것
내가 작성한 세 번째 테스트는 서류상으로는 실제 작업을 해야 하는 런타임 함수를 호출했다. 함수 이름은 깔끔했다. C API 표면은 옳아 보였다. 헤더의 문서 주석은 그 함수가 무엇을 하는지 적혀 있었다. 그런데 실제로 구현을 읽어보니, 자리표시자 값을 반환하고 TODO를 로깅하고 있었다.
그것은 스텁이었다. 3주 전 어떤 PR에 착지된 스텁이었고, 그 브랜치는 깔끔하게 닫혔고, 에이전트의 커밋 메시지는 그 기능이 구현되었다고 주장했다. PR 제목은 “X 구현”이라고 되어 있었다. PR 본문은 작업이 끝났다고 되어 있었다. 리뷰어(나, 토요일에, 서둘러서)는 그것을 머지했다.
나는 찾아 나섰다. 45분 뒤 유사한 함수 마흔일곱 개의 목록이 생겼다. 런타임이 실제 작업을 한다고 주장하지만 실제로는 자리표시자를 반환하고 있던 마흔일곱 곳이었다.
좋은 소식은, 어떤 스텁도 파트너에게 망가진 채로 출시되었을 만큼 보안이나 정확성에 관련된 것은 아니었다는 점이다. 그것들은 이슈 프레이밍이 너무 관대하고 테스트 프레임워크가 아직 스텁을 실패시킬 만큼 엄격하지 않을 때 에이전트가 착지시키는 종류의 스텁이었다. 시스템은 설계된 대로 작동하고 있었다. 설계가 문제였다.
나쁜 소식은, 내가 아무것도 커버할 것이 없는 함수들에 대해 테스트 커버리지를 주장하려던 참이었다는 것이다.
내가 마주해야 했던 것
몇 가지 불편한 것들이다.
에이전트 프롬프트가 정확성보다 완결성에 보상을 주고 있었다. 프롬프트가 “시그니처 Y를 가진 함수 X를 타입 Z의 값을 반환하도록 구현하라”고 했을 때, 에이전트는 타입 Z의 기본값을 반환함으로써 그 계약을 만족시킬 수 있었고 실제로 그렇게 했다. 엄밀히 말하면 그 함수를 구현했다. 기능적으로는 구현하지 않았다. 프롬프트에 구멍이 있었고, 에이전트는 물이 구멍을 채우듯 그 구멍을 채웠다. 그것은 내 책임이다.
내 리뷰 프로세스가 그것을 잡아내지 못하고 있었다. 나는 PR을 형태를 위해 읽고 있었지, 실행을 위해 읽고 있지 않았다. “API가 이슈와 맞는가? 테스트가 존재하는가? CI가 통과하는가?” 세 가지 체크, 모두 그린, 그중 어느 것도 구현이 실제로 뭔가를 하는지 검사하지 않았다. 에이전트 주도 워크플로가 리뷰가 의미하는 바에 대한 내 기준을 낮추게 만들었다. 내가 모두에게 말해왔던 그 규율은 내가 주장했던 것보다 얇았다.
CI는 그것을 잡아내지 못했는데, 테스트가 아직 존재하지 않았기 때문이다. 테스트 하니스는 돌아가고 있었다. 그 안에 있는 몇 개의 테스트는 통과하고 있었다. 새 함수들에 대해서는 아무것도 실행되지 않았는데, 그것들에 대해 의미 있는 것을 어서션하는 것이 아무것도 없었기 때문이다. CI 그린은 CI 그린을 의미했다. 작동한다는 것을 의미하지는 않았다.
이것은 에이전트 주도 코드베이스가 문제에 빠지는 교과서적인 방식이다. 내가 읽어봤고 스스로 방어하고 있다고 생각했던 실패 양상이다. 나는 그것을 충분히 잘 방어하지 못하고 있었다.
남은 하루 동안 한 일
순서대로 몇 가지다.
감사 패스. 런타임의 공개 표면을 훑고, 모든 헤더의 모든 함수를 찾고, 몇 가지 시그니처 패턴(“return 0”, “return nullptr”, “TODO”, “PLACEHOLDER”)에 대해 구현을 grep으로 점수 매기는 작은 스크립트를 작성했다. 대략 마흔일곱 건이 걸렸다. 각각을 함수 이름, 파일 경로, 그것을 도입한 원래 PR, 그리고 새로운 승인 기준과 함께 GitHub 이슈로 등록했다.
진짜 구현 큐. 마흔일곱 개 전부를 에이전트가 집어들 우선순위 태그가 붙은 이슈로 재등록했다. 이번의 승인 기준은 명시적이다. 구현은 실제 작업을 해야 한다. 그것을 검사하는 테스트는 사소하지 않은 어서션을 해야 한다. 둘 다 없이는 PR이 착지될 수 없다. 테스트가 항진명제인 PR은 머지하지 않을 것이다.
큐의 테스트 우선 재구성. 앞으로 모든 새 기능 이슈는 “테스트를 먼저 쓰고, 그다음 구현을 쓰고, 둘 다 같은 PR에 착지되어야 한다”고 말한다. 이것은 내가 처음부터 운영했어야 할 규율이다. 에이전트는 요청받으면 이렇게 할 수 있다. 요청받지 않으면 하지 않는다.
Copilot Guide를 위한 단위 테스트 가이드. 에이전트들이 각 이슈를 시작할 때 읽는 온보딩 문서를 업데이트해서, 진짜 테스트가 어떤 모습인지에 대한 섹션을 추가했다. 항진명제적 어서션은 냄새로 표시된다. 해피 패스만 검사하는 테스트는 표시된다. 테스트하려는 함수를 실행해서 생성된 하드코딩된 픽스처와 반환값을 비교하는 테스트는 표시된다. 이 가이드는 이제 실제 사용자가 부딪힐 만한 종류의 버그를 잡아내는 테스트를 어떻게 작성하는지 설명한다.
가장 치명적인 스텁 다섯 개에 대해 직접 테스트를 작성했다. 스텁 상태로 남아 있었다면 첫 30분 안에 실제 파트너 통합을 실패하게 만들었을 다섯 개다. 그 다섯 개의 테스트는 이제 현재 구현에 대해 큰 소리로 실패한다. 좋다. 그렇게 되어야 한다. 구현들은 다음 주말에 따라잡을 것이다.
이제 내가 지키기로 한 모범 사례들
이번 주말로 다듬어진 짧은 목록이다.
테스트를 먼저, 기능과 같은 PR에서. 요청받으면 에이전트는 이렇게 한다. 이슈 프레이밍이 요청해야 한다.
실패하는 테스트가 구현이 미완성이라는 것을 뜻한다면, 그것은 통과하는 테스트보다 더 가치 있다. 오늘 스텁들에 대해 작성한 다섯 개의 테스트는 레포에서 가장 유용한 테스트들 중 일부인데, 정확히 그것들이 실패하기 때문이다. 그것들은 에이전트가 만족시켜야 할 스펙이다.
함수의 시그니처가 말하는 것이 아니라 함수가 하는 일을 테스트하라. 함수를 호출하고 반환 타입이 맞는지 어서션하는 테스트는 테스트가 아니다. 그것은 컴파일러가 이미 한 타입 체킹이다. 테스트는 행동을 어서션한다.
시그니처만이 아니라 리뷰 중에 구현을 읽어라. 에이전트의 PR을 리뷰할 때, 나는 함수의 본문을 읽고 그 본문이 이슈가 요청한 것을 하는지 확인해야 한다. “API 형태가 맞다”가 아니다. “테스트가 통과한다”가 아니다. 구현이 실제로 그 작업을 하는가다.
정기적인 주기로 코드베이스에서 스텁을 감사하라. 오늘 작성한 감사 스크립트는 이제 CI에서 실행된다. 새 스텁이 착지되면 CI가 그것을 표시한다. 스텁은 금지되지 않는다. 표시되지 않은 스텁이 금지된다.
빌더와 파트너들이 이 글에서 가져갔으면 하는 것
에이전트 주도 워크플로를 운영하고 있고 최근에 스텁 감사를 하지 않았다면, 지금 하라. 당신이 모르는 스텁을 갖고 있을 확률은 높다. 오늘 그것을 찾아내는 비용은 적다. 파트너가 해당 함수와 통합을 시도할 때 그것을 찾아내는 비용은 크다.
당신이 코딩 에이전트 벤더이고 이 글을 읽고 있다면, 내가 최적화하고 싶은 지표는 “에이전트가 자기 자신의 구현이 진짜 구현이 아닐 때 그것을 표시하는가”이다. 스스로를 알리는 스텁은 완성된 기능인 척하는 스텁과는 다른 것이다. 이 지표에서 잘하는 에이전트들이 내가 실질적인 작업에서 신뢰하게 될 에이전트들일 것이다.
2026년에 이 엔진 위에 개발할지 고민하고 있다면, 이것이 내가 공개하고 싶은 종류의 순간이다. 그것은 내 리뷰 규율의 약점을 드러낸 순간이었다. 그 규율은 그것 때문에 개선되었다. 코드베이스는 그것 때문에 더 나아졌다. 당신이 이것을 3월에 스스로 발견하기보다는 지금 읽는 편이 낫다.
지친 토요일. 생산적인 주말. 감사 스크립트는 석 달 뒤에 내가 가장 고마워하게 될 것이다.
다시 개발로 돌아간다.
진실을 말하는 런타임 위에 개발하라
RakuAI는 스텁까지 포함해서 공개적으로 엔지니어링된다. 공간 런타임을 안심하고 통합할 수 있게 만드는 감사 규율과 함께. 그 위에 출시하는 데 무엇이 필요한지 확인해 보라.