코드 리뷰어를 자체 검증기에 적용해 보았습니다. 그 결과 두 가지 거짓말하는 방법을 찾아냈습니다.
요약
코드 리뷰 도구인 SeamStress의 자체 검증 프로세스를 통해 발견된 두 가지 논리적 결함을 분석합니다. 증거 없는 검증과 잘못된 결과에 증거가 첨부되는 문제를 해결하기 위한 스키마 및 권한 확인 로직의 개선 방법을 다룹니다.
핵심 포인트
- 코드 리뷰 도구의 신뢰성을 위한 검증 게이트의 중요성
- 단순 ID 매칭이 아닌 실제 증거(evidence) 존재 여부 확인 필요
- 스키마 최소값 검사만으로는 공백 인용문 등의 변종을 막기 어려움
- 결과 ID 네임스페이스 처리 과정에서의 잠재적 결함 식별
저는 SeamStress를 만들었습니다. 이것은 단 하나의 규칙을 가진 코드 리뷰어입니다: 실제 코드에 대해 증명할 수 있는 내용만을 인용하여 정확한 라인을 바탕으로 보고한다는 것입니다. 만약 증명할 수 없다면, 해당 발견 사항은 판단(judgment call) 단계로 격하됩니다. 사실로서 제시되지 않습니다.
그 규칙은 하나의 작은 코드 조각인 검증 게이트(verification gate)에 의해 강제됩니다. 이 게이트는 발견 사항이 verified_real로 표시될 수 있는지 여부를 결정합니다. 도구의 다른 모든 부분은 틀릴 수 있으며 그 피해는 제한적입니다. 하지만 만약 게이트가 틀린다면, 도구는 증명 라벨을 붙인 채 전혀 얻지 못한 확신에 찬 주장을 성공으로 표시하며 조용히 보여주게 됩니다.
그래서 저장소(repo)를 공개하기 전에, 저는 이 도구를 게이트 자체에 실행해 보았습니다. 다른 누구의 코드에 실행되는 것과 동일한 파이프라인을 사용했습니다: 세 명의 눈먼 비평가(three blind critics), 그 다음 합성(synthesis), 그리고 각 발견 사항에 대한 검증(per finding verification) 순서입니다. 총 8번의 모델 호출이 이루어졌습니다. 그 결과, 도구는 자체 기반에서 두 가지 치명적인 결함을 찾아냈습니다.
결함 하나: 근거 없는 검증
상태 권한(status authority)은 다음과 같았습니다:
const result = verifications.find((v) => v.findingId === finding.id);
return result ? result.status : "unverified";
이 코드는 finding ID 매칭 결과만을 신뢰했습니다. 증거(evidence)는 전혀 확인하지 않았습니다. 그리고 스키마(schema)는 빈 증거 배열(empty evidence array)과 빈 인용 코드 문자열(empty quoted code string)을 허용했습니다. 따라서 {status: "verified_real", evidence: []}와 같은 형태의 결과는 깔끔하게 검증되었고, 발견 사항을 증명된 것으로 인증했습니다. 보고서 렌더러(report renderer)는 해당 발견 사항을 헤드라인에 배치하고, 증거로 인용된 정확한 라인을 약속하는 문구 아래에 아무것도 첨부하지 않은 채 표시할 것입니다. 증거 블록은 누락된 증거의 표시를 억제했습니다. 하지만 검증된 세트에서 해당 발견 사항을 제거하지는 않았습니다.
해결책은 단순히 스키마뿐만 아니라 권한(authority) 단계에 존재합니다:
if (!result) return "unverified";
const hasRealEvidence = result.evidence.some((e) => e.quotedCode.trim().length > 0);
return hasRealEvidence ? result.status : "unverified";
최소 하나 이상의 비어 있지 않은 인용문(quote)이 이를 뒷받침할 때만 판결(verdict)이 인정됩니다. 권한 확인(authority checking) 과정을 통해, 단순한 스키마 최소값(schema minimum) 검사로는 놓칠 수 있는 공백만 있는 인용문(whitespace quote) 변종도 잡아낼 수 있습니다. 5fdd680에서 수정되었습니다.
두 번째 결함: 잘못된 결과에 증거가 첨부됨
결과 ID(Finding IDs)는 파일 경로의 슬러그(slug)를 통해 네임스페이스(namespaced) 처리되었습니다. 이 슬러그는 모든 비-알파뉴메릭(non-alphanumeric) 연속 문자를 소문자로 변환하고 대시(-)로 압축합니다:
const slug = path.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
서로 다른 두 경로가 동일한 슬러그 값을 가질 수 있습니다. 예를 들어 a/Check.ts와 a-check.ts, 또는 user_check와 user-check가 그러합니다. 이런 일이 발생하면 두 개의 심(seam)이 동일한 네임스페이스 접두사를 공유하게 되고, 결과 ID가 별칭(alias) 관계가 됩니다. 이로 인해 첫 번째 일치하는 조회(lookup)가 한 심의 검증된 상태와 인용된 증거를 다른 심의 결과에 바인딩(bind)하게 됩니다. 즉, 검증된 적이 없는 결과에 조작된 증거가 붙게 되는 것입니다. 이를 유발하려면 경로가 충돌하는 쌍이 필요하므로 드문 일이지만, 발생했을 때의 결과는 최악입니다.
수정 사항은 네임스페이스를 맵(map) 내 심의 위치를 기준으로 설정하여, 구조적으로 고유하도록 만들었습니다. 이제 충돌이 발생하더라도 중복된 ID가 생성될 수 없습니다. bb9c838에서 수정되었습니다.
이야기가 아닌 테스트를 믿으세요
두 가지 수정 사항 모두 회귀 테스트(regression tests)로 고정되었으며, 이 테스트들은 되돌리기(reversion)를 통해 증명되었습니다. 이는 비유가 아닙니다. 우리는 임시 워크트리(scratch worktree)에서 각 수정 사항을 되돌리고 테스트는 HEAD 상태로 유지한 채, 수정 전 코드에서는 가드(guards)가 빨간색(실패)으로 변하고 양성 대조군(positive control)은 초록색(성공)을 유지하는 것을 확인했습니다. 증거 게이트(evidence gate)를 되돌리면 두 개의 테스트가 실패합니다. 충돌 수정 사항을 되돌리면 바인딩 테스트가 실패합니다. 어느 쪽이든 수정 사항을 복구하면 테스트 스위트(suite)는 다시 초록색이 됩니다. 여러분도 직접 해볼 수 있습니다. 테스트는 src/types/types.test.ts와 src/engine/detector.test.ts에 있습니다.
관련된 하나의 격차(gap)가 발견되었으나 의도적으로 열려 있는 상태로 두었습니다. 발견 ID가 무엇과도 일치하지 않는 고립된 검증(orphaned verification)은, 해당 발견 사항을 검증되지 않은 것으로 조용히 격하시킵니다. 이는 과소 보고(under reporting)에 해당합니다. 이는 잘못된 확신을 주는 대신 침묵을 택함으로써 안전한 방향으로 실패한 것입니다. 따라서 수정하기보다는 문서화되었습니다. 모든 발견 사항이 커밋(commit)될 가치가 있는 것은 아닙니다.
놓치고 있는 것
도구는 실패 사례를 기록했으며 이는 공개되어 있습니다. 벤치마크는 문서화된 사건으로부터 재구성된 실제 버그를 추가 전용 원장(append only ledger)에 기록하며, 이 원장에는 놓친 사례(misses)도 포함됩니다. 하나의 피스처(fixture)는 리뷰 단계에 도달조차 하지 못했습니다. 키워드 사전 필터(keyword pre filter)가 점수를 0점으로 매겼고, 모델이 호출되지 않았기 때문에 실행 비용도 들지 않았습니다. 이는 탐지 단계에서의 누락(detection stage miss)이며, 우리가 추적하는 한계의 구체적인 사례입니다. 이는 원장에 기록되어 있으며, 편집되어 삭제되지 않았습니다.
더 광범위한 한계점들은 리포지토리(repo)에 명시되어 있습니다. 아직 초기 단계이며, 사용자의 API 키를 직접 사용해야 하고, 적은 수의 리포지토리에서 검증되었습니다. 도구는 눈앞에 있는 코드에 대해 추론하므로, 이슈 트래커(issue tracker)에 남아 있는 설계 의도(design intent)를 볼 수 없습니다. 발견 사항이 코드상으로는 정확하더라도, 당신이 이미 의도적으로 결정한 사항일 수 있습니다.
이를 공개하는 이유
감사(audit) 자체가 논거이기 때문입니다. 증명 표준(proof standard)을 주장하는 코드 리뷰어는 스스로의 방법론을 견뎌내야 하며, 그 이야기의 정직한 버전에는 게이트(gate)가 수정될 때까지 두 번이나 실패했던 부분도 포함되어야 합니다. 도구에 대한 신뢰는 도구가 발견 사항을 찾아내는 것과 동일한 방식으로 얻어야 합니다. 실제 코드와 대조하고, 정확한 라인을 인용하는 방식으로 말입니다.
각 발견 사항에 대한 검증기의 인용 증거를 포함한 전체 엔지니어링 기록은 리포지토리에 있습니다: docs/seamstress-trust-gate-trio.md. 실제 출력을 확인하는 가장 빠른 방법은 examples/입니다. 누락 사례를 포함한 벤치마크는 benchmark/에서 확인할 수 있습니다.
구현은 AI의 도움을 받았습니다. 아키텍처 (Architecture), 검증 (Validation), 그리고 모든 되돌릴 수 없는 호출 (Irreversible call)은 제가 직접 수행했습니다.
SeamStress는 오픈 소스입니다: https://github.com/SeamStressDev/seamstress
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기