이미 배포한 커밋을 측정한 뒤 되돌리다
측정 없이 들어간 커밋 하나를 뒤늦게 측정했습니다. 세 변경 중 둘이 지거나 이득이 없었고 전부 되돌렸습니다. 대신 그 실험이 드러낸 다른 결함은 실측 영향 범위가 9건이라 고치지 않고 기록으로 남겼습니다.
- 새 구현이 오라클과 일치한 횟수 — 사전에 정한 규칙대로 되돌림
- 0 / 3
- 관대한 파서가 실제로 복구한 호출 — 겨냥한 실패는 고칠 수 없는 것이었음
- 0 / 60
추출 파이프라인에는 LLM 판정자가 하나 있습니다. 추출된 관계를 노트 원문과 대조해 근거 없는 것을 떨어냅니다. 어느 커밋이 이 판정자가 읽는 원문을 바꾸고, 표에서 결정론적으로 적재된 관계는 판정 대상에서 빼고, 추출 결과 파싱을 관대하게 바꿨습니다. 셋 다 측정 없이 들어갔습니다.
바꾼 이유 자체는 타당했습니다. 판정자를 켜는 게이트는 산문 기준으로 계산되는데 판정자가 읽는 텍스트는 잘린 다른 텍스트였으니, “창이 하나면 판정자가 원문을 본다”는 전제가 거짓이었습니다. 그 지적은 옳습니다. 다만 새 텍스트가 더 나은 판정을 낸다는 결론은 거기서 따라 나오지 않습니다. 그것을 아무도 확인하지 않았습니다.
영향 범위를 먼저 쟀다
이 변경은 노트에 표가 있고, 표를 잘라낸 뒤에도 산문이 한 창에 들어가야만 동작합니다. 세 볼트를 전수 조사했습니다.
| 볼트 | 노트 | 표 보유 | 게이트 통과 |
|---|---|---|---|
| Market | 4,306 | 78 | 47 |
| news | 314 | 0 | 0 |
| e2e | 2,615 | 1 | 1 |
7,235개 노트 중 48개, 0.66%입니다. 내용 중복을 제거하면 문서 15개이고 전부 특정 기업의 공시입니다. 표본이 아니라 전수라서 샘플링이 필요 없었습니다.
가정이 아닙니다. 영향 범위 안 노트 36개는 변경 이전 로그에 이미 실제 판정 기록을 갖고 있습니다. 판정자는 그 노트들에서 실제로 동작했습니다.
실험
관계 집합을 고정하고 판정자가 읽는 원문만 바꿨습니다. 두 조건이 어긋난 모든 관계는 오라클로 보냈습니다. 오라클은 노트 전체를 자르지 않고 표까지 포함해 읽으므로 두 조건 어느 쪽보다 정보가 많고, 독립 3표로 판정하며 2대 1로 갈리면 반올림하지 않고 미확정으로 보고합니다.
판정자 응답의 판정 개수가 입력 개수와 맞지 않으면 실패한 호출로 버리고 채우지 않습니다. 채우면 그 조건이 “전부 유지”로 조용히 채점됩니다.
결과 — 새 원문이 더 나쁘다
| 항목 | 값 |
|---|---|
| 비교한 관계-판정 쌍 | 121 |
| 두 조건이 어긋난 것 | 3 |
| 그중 기존이 오라클과 일치 | 3 |
| 그중 신규가 오라클과 일치 | 0 |
| 오라클 2대 1 미확정 | 0 |
| 실패 호출 (제외, 미충전) | 4 |
세 건 모두 같은 실패이고, 메커니즘은 가정과 정반대였습니다.
| 관계 | 기존 | 신규 | 오라클 |
|---|---|---|---|
| 임원 A가 직책 X를 보유 | 삭제 | 유지 | 근거 없음 |
| 임원 B가 이사회로 이동 | 삭제 | 유지 | 근거 없음 |
| 임원 B가 회사를 이끈다 | 삭제 | 유지 | 근거 없음 |
표를 잘라내는 것은 판정자에게 산문을 더 깨끗이 보여주는 게 아니라, 잘못된 사실을 반박할 증거를 치우는 것이었습니다. 최고경영자 교체를 알리는 공시에서, 그 이동을 적어둔 표가 바로 “이 사람이 회사를 이끈다”는 관계를 기각할 근거입니다. 표를 지우면 판정자는 관대해집니다.
완전한 산문보다 덜 완전한 산문에 표를 더한 쪽이 낫습니다.
통계를 정직하게 적으면
3대 0 부호검정은 양측 p=0.25입니다. 유의하지 않습니다. 검정력이 부족한 구간입니다. 그런데 더 얻을 검정력이 없습니다. 영향 받는 모집단이 문서 15개, 판정 쌍 121개이고 그것이 만들어낸 불일치가 3건입니다.
그래서 판정 규칙을 실행 전에 문서로 고정해두었습니다. “신규가 기존을 이겨야 한다. 지거나 비기면 되돌린다.” 입증 책임은 현상 유지가 아니라 변경에 있기 때문입니다. 신규는 3전 0승이었습니다.
되돌린 것은 원문 변경, 그것에 딸린 판정 면제, 그리고 그 둘이 만든 결함 두 가지입니다. 하나는 게이트 회귀입니다. 게이트 상수는 “관계가 적은 대화형 노트가 과도하게 잘린다”는 이유로 존재하는데, 게이트가 세는 개수는 분리 이전 값이라 표 50행과 산문 2건을 가진 노트가 게이트를 통과한 뒤 판정자를 산문 2건에만 돌립니다. 상수가 막으려던 바로 그 구간입니다. 다른 하나는 낭비되는 유료 호출입니다. 면제가 모든 관계를 면제로 보낼 수 있는데, 그 경우 결과를 바꿀 수 없는 왕복이 하나 발생합니다.
하나는 의도적으로 남겼습니다. 판정 대상이 비었을 때 호출을 건너뛰는 가드입니다. 그 경로는 되돌린 커밋 이전부터 도달 가능했고, 응답이 어떤 결과도 바꿀 수 없는 요청을 생략하는 것은 동작상 위험이 없습니다.
세 번째 변경 — 관대한 파싱
같은 커밋이 추출 결과 파싱을 엄격 모드에서 폴백 모드로 바꿨습니다. 객체 뒤에 토큰 하나가 딸려 나오는 것 때문에 노트 하나가 통째로 실패하고 재시도 횟수를 하나 쓰는 일을 막으려는 것이었습니다.
폴백은 스트리밍 파서라 첫 번째 완전한 JSON 값을 읽고 멈춥니다. 그래서 엄격 모드와 갈라질 수 있는 경우가 다섯 가지로 닫힌 집합입니다.
| 모델 출력 | 엄격 | 관대 | |
|---|---|---|---|
| 완전한 객체 + 뒤에 잡토큰 | 실패 | 온전히 복구 | 유일한 이득 |
| 잘리거나 짝이 안 맞음 | 실패 | 거절 | 동일 |
| 앞에 코드 펜스 | 실패 | 거절 | 동일 |
| 앞에 완전한 객체, 그 뒤에 결과 | 실패 | 빈 결과 반환 | 조용한 데이터 손실 |
| 앞에 스칼라, 그 뒤에 결과 | 실패 | 거절 | 동일 |
네 번째 행이 문제입니다. 결과 구조체의 모든 필드에 기본값이 있어서, 앞에 아무 JSON 객체나 오면 완전히 빈 결과로 역직렬화됩니다. 노트는 엔티티 0개 관계 0개로 성공 기록되고, 엄격 모드였다면 실패 후 재시도했을 자리입니다.
실측했습니다. 볼트를 결정론적 간격으로 훑어 60회 호출입니다.
| 항목 | 값 |
|---|---|
| 사용 가능한 호출 | 60 |
| 엄격 파싱 성공 (폴백 미사용) | 58 |
| 엄격 실패, 관대가 내용 복구 | 0 — 변경이 이기는 유일한 경우 |
| 엄격 실패, 관대가 빈 결과 복구 | 0 |
| 엄격 실패, 관대도 거절 | 2 |
실패 2건은 모델이 JSON 없이 산문으로 답한 경우입니다. 그것이 이 커밋이 동기로 인용한 바로 그 실패 모드이고, 폴백은 그 경우를 고칠 수 없습니다. 겨냥한 실패는 손이 닿지 않는 곳에 있었고, 손이 닿는 실패는 60회 중 한 번도 일어나지 않았습니다.
되돌렸습니다. 다만 다섯 경우를 못 박은 테스트는 남겼습니다. 폴백 함수는 다른 두 곳에서 여전히 쓰이므로 “앞에 객체가 오면 빈 결과”라는 위험은 살아 있는 지식이고, 그 테스트가 재제안 금지 기록의 실행 가능한 형태입니다.
실험이 드러낸 진짜 결함, 그리고 고치지 않기로 한 결정
같은 오라클로 실제 프로덕션 삭제 기록을 채점했습니다. 42건입니다. 평평하게 세면 판정자는 맞을 때가 더 많습니다. 그런데 평평하게 세면 안 됩니다. 로그에 관계의 출처가 기록되지 않아 산문 추출과 표 적재가 섞여 있기 때문입니다.
출처는 결정론적으로 가를 수 있습니다. 삭제된 관계의 객체 텍스트가 그 노트의 표 영역 안에 나타나는지 보면 됩니다. LLM 호출이 추가로 필요 없는 문자열 검사입니다.
| 출처 | 판정자가 틀림 | 판정자가 맞음 |
|---|---|---|
| 표에서 온 것 | 8 | 0 |
| 산문에서 온 것 | 8 | 26 |
판정자는 결정론적 표 행에 대해 단 한 번도 맞은 적이 없습니다. 그리고 산문에서는 실제로 유용합니다.
그런데 같은 검사를 채점 표본이 아니라 로그 전체에 돌리면 결론이 뒤집힙니다.
| 볼트 | 전체 삭제 | 표에서 온 것 | 영향 노트 |
|---|---|---|---|
| Market | 3,215 | 9 (0.3%) | 2 |
| e2e | 1,781 | 0 | 0 |
볼트의 전체 기록에서 9건이고, 그 9건은 같은 공시 문서 2개입니다. 이유는 게이트에 있습니다. 의미 있게 큰 표는 노트를 여러 청크로 쪼개서 게이트가 실패하고, 판정자가 아예 돌지 않습니다.
고치지 않기로 했습니다. 면제를 넣으려면 앞에서 제거한 게이트 회귀를 되살려야 하고, 스키마 오분류가 가능한 부류에 대한 유일한 검사를 없애게 되며, 전체 삭제의 0.3%를 바꿉니다. 결함은 실재하고 발생 시 오류율은 8/8이지만, 총 영향 범위는 관계 9건입니다. 고치지 않고 기록했습니다.
다시 열 조건도 함께 적었습니다. 이 비율은 표가 아니라 게이트의 함수이므로, 게이트 통과 범위를 넓히는 어떤 변경이든 훨씬 많은 표 노트를 판정자의 사정거리 안으로 끌어옵니다. 그때는 0.3%라고 가정하지 말고 위 분류를 다시 돌려야 합니다.
이 측정이 보여주지 않는 것
- 오라클은 사람이 아니라 모델이고, 판정자와 같은 노트를 읽습니다. 노트에 없는 사실은 양쪽 모두에게 보이지 않습니다.
- 두 조건이 동일하게 처리한 관계는 채점하지 않았으므로, 이것은 변경분을 잰 것이지 판정자의 절대 정확도가 아닙니다. 121쌍 중 118쌍은 일치했습니다.
- 오라클 자체의 한계가 데이터에 보입니다. 하나의 표에서 이름만 다른 인수 기관 행들에 대해 오라클이 갈렸습니다. 이름만 다른 행이 서로 다른 진위를 가질 수는 없습니다.
- 관대한 파싱의 0/60은 95% 상한이 약 5%입니다. 그 경우가 절대 없다는 증명이 아니고, 실행 전에 고정한 규칙(입증되지 않은 이득은 남지 않는다)에 따른 되돌림입니다.
- 영향 노트가 있는 볼트가 하나뿐이라, 표의 내용이 다른 코퍼스로 일반화되지 않습니다.
측정 기록
| 항목 | 값 |
|---|---|
| 실행 시점 | 2026년 7월 26일, 오염 제거 재분석 7월 27일 |
| 하니스 | tagging/eval_extraction_quality.rs::verify_judge_source_ab, tolerant_parse_rate |
| 조건 | 관계 집합 고정, 판정자 입력 텍스트만 교체 |
| 오라클 | 노트 전문(표 포함), 독립 3표, 2대 1은 미확정 보고 |
| 판정 규칙 | 실행 전 문서로 고정: 신규가 이겨야 하며 무승부는 되돌림 |
| 파싱 실측 | 볼트를 결정론적 간격으로 훑어 60회 호출, sonnet-5 |
파싱 실측은 프록시가 아니라 API에 직접 호출합니다. 프로덕션은 인증 프록시를 거치므로 뒤따르는 토큰의 동작이 엔드포인트 간에 다를 수 있습니다.
어느 테스트도 판정자의 입력 텍스트를 보호하지 않습니다. 되돌린 변경도, 이 되돌림도 가드가 없습니다. 유일한 보호는 이 기록과 하니스입니다.
측정 기록 원본은 Consilience 저장소의 docs/details/verify-judge-source-2026-07-26.md에 있습니다.
무엇을 측정한 것인가
- Consilience
세계 최초의 범용 온톨로지 OS — 마크다운 문서에서 지식그래프를 자동으로 구축하고, 그 그래프를 대상으로 에이전트가 추론합니다