Skip to main content

검증 주장 무결성

업데이트 2026-08-13 8분 분량 GitHub에서 수정 ↗

검증 주장 무결성

에이전트가 “테스트를 통과했습니다”, “커버리지 87%입니다”, “이 코드는 더 이상 쓰지 않으니 지워도 됩니다"라고 말할 때, 그 말을 어떻게 믿을 수 있을까요? 검증 주장 무결성 (Verification-Claim Integrity) 은 바로 이 지점을 다룹니다. 관찰하지 않은 성공을 주장하지 않고, 검증하지 않은 결함을 주장하지 않는 규칙입니다. 이 규칙이 없으면 “테스트를 통과했다"는 말이 실제로 명령을 돌린 관측인지, 아니면 ‘된 것 같다’는 추측인지 분간이 안 됩니다. 왜냐하면 추측이 하네스의 다른 부분으로 퍼지면 증거 없는 완료가 쌓이고, 그 위에 다음 작업이 올라가기 때문입니다. 그래서 MoAI-ADK는 harness 안의 모든 완료·결함·권고 주장이 직접 관측된 증거로 귀속되도록 강제합니다.

왜 이 규칙이 필요한가

에이전트는 “다 됐습니다"라고 말하는 데 학습적으로 편향되어 있습니다. 사용자가 듣고 싶어 하는 말이 무엇이든, 결과를 긍정적으로 요약해 보고하는 쪽으로 훈련된 그래디언트가 있습니다. 이 편향을 시스템이 보정하지 않으면 “통과했다"는 말이 믿을 수 없게 됩니다.

더 위험한 방향이 있습니다. 에이전트가 “이 SPEC은 닫기 처리가 빠져 있다”, “이 패키지는 커버리지가 낮다”, “이 기능은 아직 쓰이고 있으니 지우면 안 된다"고 주장할 때, 그 주장이 사실이 아닐 수 있습니다. 텍스트 패턴만 보고 결함을 추론하거나, 참조가 존재한다는 이유만으로 살아있는 기능이라고 판단하면, 존재하지 않는 문제를 고치거나 이미 제거된 코드를 살리려다 낭비가 생깁니다.

주의
증거 부재는 성공의 증거도, 실패의 증거도 아닙니다. 검사를 돌리지 않았다는 것만으로 “통과했다"거나 “실패했다"고 말할 수는 없습니다. 둘 다 관측되지 않은 주장입니다.

불변량 — 관찰되지 않은 주장 금지

핵심 규칙은 한 문장입니다.

에이전트는 직접 검증하지 않은 완료, 결함, 부채, 드리프트, 혹은 권고의 전제를 주장해서는 안 된다.

이 규칙은 양쪽으로 묶입니다.

  • 성공 방향 — “테스트가 통과했다”, “커버리지 87%이다”, “린트가 깨끗하다"는 주장은 실제로 명령을 돌리고 그 출력을 관찰했을 때만 성립합니다. 돌리지 않은 명령, 건너뛴 단계는 빈칸이지 통과가 아닙니다.
  • 결함 방향 — “이 SPEC은 닫기 빚이다”, “이 패키지는 커버리지가 낮다”, “이 코드는 드리프트다"는 주장도 도메인의 전용 도구로 검증했을 때만 성립합니다. 프론트매터 텍스트나 grep 결과만으로 결함을 추론하면 관찰되지 않은 결함 주장입니다.

결함 방향이 더 위험합니다. 잘못된 “지워라” 주장은 다음 빌드나 테스트가 곧바로 반박하지만, 잘못된 “그대로 둬라” 주장은 죽은 코드를 살려두고 아무 신호도 내지 않습니다.

네 가지 결합 표면

규칙은 한 표면에만 묶이지 않습니다. 관측되지 않은 주장이 스며들 수 있는 네 곳을 모두 묶습니다.

표면묶는 대상
오케스트레이터 자기 보고완료 보고서와 검증 매트릭스의 모든 PASS 행“모든 검증을 통과했습니다” 배너의 각 줄
에이전트 완료 보고서에이전트의 자기 검증 매트릭스 (테스트·빌드·커버리지·린트)“테스트 PASS, 커버리지 87%” 보고
결함·부채·드리프트 주장결함이나 기술 부채가 “존재한다"는 모든 주장“SPEC X는 닫기 빚이다”, “패키지 Y는 커버리지가 낮다”
권고의 전제 주장“유지하라/제거하라” 권고의 이유가 되는 전제“이 기능은 아직 살아있다”, “다른 소비자가 의존한다”

네 번째 표면은 권고의 이유를 검증해야 한다는 규칙입니다. “제거하면 안 된다"고 권고하려면, 그 기능의 생산자가 여전히 존재하는지, 소비자가 여전히 도달 가능한지를 직접 확인해야 합니다. 도달 가능성이 정당화가 아닙니다. 참조가 존재한다는 것은 참조가 살아있다는 증거가 아닙니다.

다섯 단락 보고 형식

이 규칙을 실제로 강제하는 운용 메커니즘이 다섯 단락 보고 형식입니다. 에이전트가 완료나 검증을 보고할 때 다섯 단락으로 나눠 작성하면, 관찰한 것과 관찰하지 않은 것을 분리하게 되고, 관찰하지 않은 부분이 빈칸으로 드러납니다.

1. 주장 (Claim)

무엇을 단언하는지 한 문장으로 적습니다. 검증 매트릭스의 한 행이나, 산문 보고의 한 문장이 하나의 주장 단위입니다.

2. 증거 (Evidence)

실제로 돌린 명령과 그 출력을 있는 그대로 적습니다. 요약이 아닙니다. 주장이 “테스트가 통과했다"면, 이 단락에는 go test ./... 명령과 그 명령이 뱉은 출력 블록이 그대로 들어갑니다. “모든 테스트가 통과했다"는 요약은 증거가 아닙니다. 출력 자체가 짐을 싣는 artifact입니다.

3. 기준 귀속 (Baseline-attribution)

이 주장을 어떤 기준에 대해 측정했는지 밝힙니다. 이번 실행에서, 이 트리에 대해 직접 돌린 명령과 관측한 출력입니다. 다른 SPEC, 다른 패키지, 다른 시점에서 기억하던 수치를 빌려오면 안 됩니다. “커버리지 87%“이라면, 방금 이 트리에서 go test -cover ./internal/<pkg>/...를 돌려서 coverage: 87.0% of statements를 관측했다는 뜻입니다.

4. 미검증 (Gaps)

명시적으로 검증하지 않은 것을 나열합니다. 이 단락이 전체 형식의 핵심입니다. 관찰하지 않은 주장이 빈칸으로 지나가는 것을 막아줍니다. 미검증 단락이 비어 있다면 “검증하지 않은 것이 없다"는 강한 주장이며, 그 자체가 참이어야 합니다. 확신이 서지 않으면 빈칸으로 두지 말고 이름을 적으세요.

5. 잔여 위험 (Residual-risk)

관측된 증거 다음에도 남는 불확실성입니다. 미검증(관찰하지 않은 것)과 다릅니다. 잔여 위험은 관찰했음에도 여전히 틀릴 수 있는 것입니다. 출렁이는 테스트, 환경 의존 동작, 뒤로 미뤄진 수용 기준, 검증 시점과 사용 시점 사이의 창 등이 여기에 해당합니다.

실제 사례 — 결함 주장의 위험

한 상태 보고서가 status: implemented이고 era: 필드가 없는 SPEC 29개를 세고, 프론트매터 텍스트만 보고 “이 29개는 V3R6 닫기가 빠진 SPEC이다"라고 추론한 뒤 일괄 닫기를 제안했습니다.

이것은 관찰되지 않은 결함 주장이었습니다. 보고자는 도메인의 전용 도구를 돌리지 않았습니다. 마침내 moai spec audit --json을 돌려보니 29개 모두 기존 특례 (grandfather) era (V3R2-R4 28개 + V2.x 1개) 로 분류되었습니다. era_final: true, 보호 대상, V3R6 3단계 닫기 대상이 아니었습니다. 전체 카탈로그의 MUST-FIX 드리프트는 0이었습니다. 추론한 “닫기 빚"은 존재하지 않았고, 일괄 닫기가 진행됐다면 보호받는 29개를 이유 없이 건드릴 뻔했습니다.

정보
교훈: 결함 주장은 도메인 도구가 확인하기 전까지 가설입니다. era: 필드가 없고 implemented인 텍스트 패턴은 두 가지 해석 (祖父 레거시 vs 현대 닫기 빚) 모두와 양립합니다. 도구만이 분기할 수 있습니다. 도메인 도구가 존재하면 (moai spec audit, go test -cover, golangci-lint) 텍스트만으로 결함을 주장해서는 안 됩니다.

실제 사례 — 유지 주장의 위험

사용자가 특정 디렉터리를 제거하라고 지시했습니다. 오케스트레이터는 artifact를 지우면서 한 항목만 빼두었습니다. 제거하면 “모든 분산 사용자에게서 살아있는 기능을 거둬간다"는 전제였고, 별도의 은퇴 SPEC을 권했습니다.

그 전제는 한 번도 검증되지 않았습니다. 오케스트레이터는 해당 스캔이 도달 가능하다는 것과 SPEC이 아직 status: implemented로 읽힌다는 것만 확인했고, 둘 다 그 기능이 살아있다는 증거로 취급했습니다. 둘 다 그렇지 않습니다. 생산자를 직접 열거해 보니 이미 전부 사라졌습니다. 명령도, 워크플로우도, 에이전트도, CLI도, 스캐폴드도, 4로케일 문서 페이지도 없었습니다. 이미 완료된 은퇴 SPEC이 그 기능을 분산 사용자 모두에게서 영구히 제거했고, 뒤따른 정리 커밋이 남은 고아를 쓸어냈습니다. 스캔은 두 차례의 정리를 그냥 견뎠을 뿐입니다.

정보
교훈: 도달 가능성이 정당화가 아니며, SPEC이 아직 status: implemented로 읽힌다고 해서 그 기능이 살아있다는 증거도 아닙니다. 뒤따른 SPEC이 은퇴시켰을 수 있습니다. 사용자의 지시에 반하는 유지 권고를 내리려면, 유지하려는 것의 생산자를 열거하고 완료된 은퇴 SPEC이 있는지 확인해야 합니다. 전제를 검증하지 않은 이의 제기는 관찰되지 않은 주장입니다.

사용자에게 이 규칙이 왜 중요한가

이 규칙은 에이전트의 보고를 읽을 때 “근거가 무엇인가?“를 묻는 습관의 시스템적 표현입니다. MoAI-ADK는 에이전트가 “통과했다"고 끝내는 대신 다섯 단락으로 나눠 보고하도록 강제하고, 도메인 도구로 직접 검증한 결과만 증거로 인정합니다. 그 결과:

  • 완료 보고를 신뢰할 수 있습니다 — “테스트 통과"가 곧 실제 명령과 출력을 의미합니다.
  • 거짓 결함으로 코드를 건드리는 일이 줄어듭니다 — 결함 주장은 도구 확인을 거칩니다.
  • 죽은 코드가 살아나는 일을 막습니다 — 유지 권고는 생산자 존재를 확인해야 합니다.

TRUST 5 품질의 “추적 가능” (Trackable) 원칙이 여기서 현실이 됩니다. 모든 주장이 관측된 증거로 귀속될 때, 보고는 비로소 감사 가능해집니다.

관련 문서