Evidence Graph

컴파일 에러로 강제하는 100% 명세 커버리지

https://github.com/samchon/ttsc/tree/master/packages/evidence

TL;DR

  • 컴파일러 하네스, Evidence Graph
    • Loop Engineering 불필요
    • @evidence <target> <reason>
    • @evidenceReview <target> <reason>
    • @evidenceExclude <target> <reason>
  • Spec Driven Development
    • 사람은 요구사항만 쓰고 검토한다
    • 나머지는 AI가 100% 커버리지로 만든다
    • 프로그래밍과 문서/문학에 적용된다
요구사항 커버리지
Plain
51.6%
Evidence
100%
토큰 사용량
Plain
5,449M
Evidence
411M
테이블 100개 이상 · 15만 줄 이상

명세를 다 지켰냐는 물음에, 사람은 설명하고 컴파일러는 빌드를 멈춘다

규칙 문서를 다 읽었냐는 물음에, 사람은 다시 읽어주고 컴파일러는 파일마다 따로 묻는다

현재의 한계

우리가 결국 루프를 돌게 된 이유

알겠다고 답하는 것과 지키는 것은 다르다

  • 기본 조건에서 프런티어 모델 6종의 실제 절차 준수율은 60건 중 0건이었다
  • 같은 실행에서 말로 답한 준수율은 90% 이상이었다
  • 규칙 8개 조건에서는 개별 준수율이 약 41%여도 전부 지킨 응답은 5.7%였다
  • 최상위 모델도 규칙 7개부터 전체 준수율이 50% 아래로 떨어졌다

도구 실행 로그와 결정론적 검사기로 측정했다 (2605.01771) (2608.12426)

명세가 쪼개지고 작업이 길어지면 나빠진다

  • 명세를 약 60개 요청으로 나누면 일괄 전달보다 충실도가 낮았다: Claude Code 16/20, Codex 14/20
  • 15개 에이전트 중 누구도 36개 반복 확장 문제를 끝까지 풀지 못했다. 최고 엄격 통과율은 14.8%였다
  • 구조 침식은 실행 궤적의 77%, 장황성은 75.5%에서 증가했다
  • 오픈소스 Python 저장소 473개보다 에이전트 코드는 2.3배 장황하고 2배 더 침식됐다

2026년 코딩 에이전트 벤치마크 두 편 (2603.17104) (2603.24755)

그래서 Loop Engineering이 나왔다

  • 다 했다는 말은 증거가 아니다 → 전부 다시 읽는다
  • 누락은 봐야만 드러난다 → 찾은 문제를 전부 고친다
  • 하나 고치면 다른 게 깨진다 → 처음으로 되돌아간다
  • 끝났다고 말해줄 게 없다 → 빈 회차가 나와야 멈춘다

Loop Until Dry라고도 한다. 현존 최선의 수단이고, 실제로 작동한다.

ERP Loop Engineering

요구사항 커버리지
51.6%
시간 분포
10%
90%
최초 개발검토 루프
102시간작업 시간 5,449M토큰
ERP · 테이블 100개 이상 · 15만 줄 이상

Evidence Graph

명세 커버리지 누락이 컴파일 에러가 된다

먼저 산출물을 계층으로 나눈다

아이디어 노트
요구사항
설계 명세
구현
테스트

각 화살표는 자신이 인용하는 근거를 가리킨다.

관계는 규칙 하나로 선언한다

type: "typescript",
files: ["src/components/**/*.tsx"], // sources
symbol: "function",
reference: {
  type: "markdown",
  files: ["docs/specifications/*.md"], // targets
  symbol: ["h2", "h3"],
},

컴포넌트는 설계 명세를 구현한다.

하나의 문법이 네 가지 산출물을 다룬다

  • Markdown: 파일, H1-H4 섹션
  • Prisma: 데이터베이스 모델, 컬럼, 관계
  • TypeScript: 타입, 함수, 프로퍼티
  • Swagger: paths 아래의 각 오퍼레이션

코드가 명세를 인용한다

/**
 * @evidence docs/specifications/discount.md#coupon-stacking
 *           Explains the stacking limit defined by this section.
 * @evidence POST:/orders/{orderId}/coupons
 *           Explains the rejection response from this endpoint.
 */
export function CouponStackingNotice(props: IProps): JSX.Element;

@evidence <target> <reason>: 이 코드가 무엇을 구현하며, 왜 그런지.

인용이 없으면 빌드가 멈춘다

$ npx ttsc
error TS16411: [evidence/graph]
  Missing acknowledgement for
  'docs/specifications/discount.md#coupon-stacking'
  (Markdown H2 'Coupon Stacking' at docs/specifications/discount.md:3)
  • 요구사항 하나당 에러 하나 → 에러 목록이 곧 작업 목록
  • 타입 에러와 같은 빌드에서 함께 검사된다

100% 커버리지에도 거짓 인용이 섞인다

/**
 * @evidence docs/specifications/discount.md#coupon-stacking
 *           Explains the per-issuer limit.
 */
export function CouponStackingNotice(props: IProps): JSX.Element;
  • 저렴한 모델은 존재하지 않는 사실을 적기도 한다
  • 거짓 태그는 에러만 지울 뿐, 문제는 남긴다

인용이 붙으면 거짓 주장을 86-88%로 탐지하고, 오탐은 0이다 (2606.30689).

검토 대상은 인용의 진위뿐

/**
 * @evidence docs/specifications/discount.md#coupon-stacking
 *           Explains the per-issuer limit.
 * @evidenceReview docs/specifications/discount.md#coupon-stacking
 *                 #a1b2c3d4e5f6 Verified against policy section 3.
 */
export function CouponStackingNotice(props: IProps): JSX.Element;
  • 검토는 같은 선언과 같은 대상끼리 대응한다
  • 인용한 내용이 바뀌면 지문이 만료된다

Luna조차 한 번의 검토로 거짓 인용을 0으로 줄였다.

태그 목록이 곧 검토 체크리스트

검토 Plain Evidence
대상 전부 인용의 진위
루프 매 회차 재시작 태그 목록만
누락 직접 찾는다 컴파일러가 보고

누락은 컴파일러가, 거짓은 리뷰가 잡는다.

벤치마크

동일한 입력 · 엔진 · 모델 · 플러그인만 차이

커버리지: 51.6–85.5% → 100%

과제 Plain Evidence
todo 85.5% 100%
reddit 80.3% 100%
shopping 63.1% 100%
erp 51.6% 100%

Plain은 규모가 커질수록 커버리지가 떨어진다. Evidence는 100%를 유지한다.

토큰 사용량: 4.8–13.3배 절감

todo866M → 92M
reddit1,179M → 245M
shopping1,516M → 271M
erp5,449M → 411M

Plain은 파랑, Evidence는 주황.

단계별 원본 차트: https://ttsc.dev/docs/benchmark/evidence

ERP: 커버리지 100% · $4.96 · 14시간

13.3×토큰 절감
5,449M → 411M
13.9×비용 절감
$68.72 → $4.96
7.5×시간 단축
102h → 14h

검토 비중: 토큰의 90–95% → 15–41%

과제 Plain Evidence
todo 검토 90% 검토 28%
reddit 검토 95% 검토 19%
shopping 검토 95% 검토 41%
erp 검토 90% 검토 15%

진한 색은 개발, 옅은 색은 검토. 각 칸이 그 과제 토큰의 100%다.

Spec Driven Development

요구사항이 인계 지점이다.
그 아래는 AI가 100% 커버리지로 전부 만든다.

방법 A는 요구사항에서 시작한다

요구사항
설계 명세
구현
테스트

요구사항이 원천 계층이다.

방법 A: 요구사항은 사람이 쓴다

  • 사람은 docs/requirements를 직접 검토한다
  • 설계 명세, 구현, 테스트는 전부 위임한다

방금 본 네 과제 모두 이 방법을 썼다.

방법 B는 아이디어 노트에서 시작한다

아이디어 노트
요구사항
설계 명세
구현
테스트

아이디어 노트가 원천 계층이다.

방법 B: 요구사항까지 위임한다

  • 아이디어 노트를 정리하지 않고 그대로 넘긴다
  • 요구사항 작성부터 전부 위임한다
  • 아이디어 노트가 하나라도 누락되면 즉시 빌드가 깨진다

사람은 원천 계층 하나만 준다.
그 아래는 그래프가 지킨다.

요구사항도 자신의 근거를 인용한다

## Coupon stacking limit {#coupon-stacking}

<!-- @evidence docs/ideas/discount.md#discount-policy
     Carries over the per-issuer limit recorded in the idea notes. -->
  • 아이디어 노트 커버리지가 비면 요구사항 빌드가 깨진다
  • 아이디어 노트, 인터뷰, 사내 문서가 한 계층을 이룬다
  • 인용은 주석이라 렌더링된 문서는 깨끗하다

백엔드는 이렇게 동작한다

요구사항
설계 명세
DB 스키마
API 오퍼레이션
API 스키마
테스트

백엔드 산출물은 요구사항과 설계 명세로 거슬러 올라간다.

프론트엔드는 이렇게 동작한다

요구사항
설계 명세
백엔드
Hooks
화면
사용자 여정

프론트엔드 산출물은 문서와 백엔드로 거슬러 올라간다.

방법 D: 원칙만 건넨다

  • 기존 프로젝트라 문서 계층 전체를 도입하기 어렵다
  • 요구사항과 설계 명세는 위임하지 않고 직접 개발하고 싶다
  • 그래프 전체를 설계할 준비는 아직 안 됐다

docs/principles.md 하나와 claim 하나로 시작한다.

모든 원칙을 반드시 준수한다

## 하드코딩하지 마라 {#no-hardcoding}
입력과 모델에서 동작을 도출하고 특정 사례를 예외 처리하지 않는다.

## 몽키 패칭하지 마라 {#no-monkey-patching}
공개된 확장 지점을 쓰고 프로토타입이나 모듈 상태를 바꾸지 않는다.

## 보편적인 정석으로 구현하라 {#conventional-solution}
측정 없는 과최적화를 피하고 표준 자료구조와 명료한 알고리즘을 우선한다.

## 문제를 본질적으로 해결하라 {#fix-the-root-cause}
눈앞의 실패 사례만 우회하지 말고 원인을 추적해 같은 부류의 문제 전체를 해결한다.

모든 함수가 모든 원칙에 답한다

  • 선택된 함수마다 H2 원칙 전부를 확인한다
  • 각 답에는 원칙을 지킨 방법과 이유를 남긴다
  • "해당 없음"으로 빠져나가지 못하게 할 수 있다
  • 한 항목이라도 답이 없으면 컴파일 에러가 된다

원칙을 하나 추가하면 모든 함수에 새 의무가 즉시 생긴다.

모든 답은 어떻게 지켰는지 설명한다

/**
 * @evidence docs/principles.md#no-hardcoding
 *   등록된 핸들러로 조회표를 만들며 특정 사례를 분기하지 않는다.
 * @evidence docs/principles.md#no-monkey-patching
 *   공개 어댑터를 쓰며 프로토타입이나 모듈 상태를 바꾸지 않는다.
 * @evidence docs/principles.md#conventional-solution
 *   표준 Map과 선형 순회를 쓰며 추측성 인덱스나 캐시를 두지 않는다.
 * @evidence docs/principles.md#fix-the-root-cause
 *   핸들러 등록 단계에서 잘못된 이름을 차단해 조회 실패만 재시도하지 않는다.
 */
export function resolveHandler(name: string): Handler;

대상과 비어 있지 않은 이유가 모두 필요하다. 하나라도 빠지면 빌드가 깨진다.

요약

  • 명세 커버리지 누락은 컴파일 에러가 된다
  • 요구사항이 인계 지점이고, 원칙 목록만으로도 시작할 수 있다
  • 커버리지가 51.6–85.5%에서 100%로 오른다
  • 리뷰는 증거의 진실성을 본다

부록: 소설

원칙과 설정이 빌드 제약이 된다

유창함은 작가성이 아니다

  • 평탄화: 못 쓴 글은 아닌데, 누구의 글도 아니다
  • 갈등 소실: 못되게 굴 인물이 다음 문단에서 사과한다
  • 번역투: 남의 문장 구조, 관계를 안 따르는 호칭

스튜디오 사례: 쿨한 성격은 죄다 은발, 장르 불문 똑같은 권선징악 엔딩.

느낌이 아니라 측정된 실패다

  • 학습이 주제와 감정과 문체를 고르게 깎는다
  • 문예물이 가장 많이 잃는다
  • 분량이 늘수록 모순이 꾸준히 늘어난다
  • 사실 오류는 앞쪽(15-30%), 모순은 뒤쪽(40-60%)에 몰린다

Narrative Flattening (2605.27878) · ConStory-Bench (사이트)

매끄러운 장면도 거짓일 수 있다

  • 기억: 인물이 알 리 없는 사실을 쓴다
  • 창작: 역사, 지리, 동기를 어긴다
  • 모순: 앞에서 정한 숫자, 연대, 성격을 뒤에서 뒤집는다
  • 개고: 앞선 수정으로 무효가 된 장면을 남긴다
  • 망각: 설정 350개 중 안 쓰인 게 뭔지 알 길이 없다

장편의 실패는 국소적이지 않고 전역적이다.

여기서는 루프가 오히려 해가 된다

  • 회차마다 글이 모델 자신의 평균으로 끌려간다
  • 문체와 유창함은 오르고, 정확도는 거의 안 움직인다
  • 목소리는 매번 평준화되고, 프롬프트로 못 막는다

회차를 늘리면 윤이 날 뿐, 사실이 되지는 않는다.

2026년 개고 연구 두 편 (2605.13368) (2604.22142)

모든 계층이 앞선 원천을 전부 인용한다

원칙
설정
스토리라인
시나리오
원고

간선마다 막는 이탈이 다르다

  • 스토리라인, 시나리오, 원고 → 원칙: 문학적 목적
  • 스토리라인, 시나리오, 원고 → 설정: 사실, 규칙, 지식
  • 시나리오, 원고 → 스토리라인: 원인과 결과
  • 원고 → 시나리오: 정확한 실행

왜 통하는가

  • 제한된 컨텍스트 → 이 장면이 질 정확한 의무
  • 그럴듯한 창작 → 명시적 계보와 검토
  • 개고로 인한 이탈 → 영향받은 검토가 만료
  • 잊힌 복선 → 100% 역방향 커버리지

엄격한 연속성 안에서 누리는 창작의 자유.

하나의 그래프로 모든 서사를

  • 설정: 역사, 세계 규칙, 인물
  • 인과: 복선, 동기, 결과
  • 연속성: 지식, 서사 궤적, 개고
  • 역사 소설, 판타지, SF, 미스터리, 드라마
  • 나폴레옹: 원칙 25개, 설정 약속 350개, 장면 742개

참고 자료: @ttsc/evidence

참고 자료: 코딩 에이전트

  • 명세가 쪼개져 오면 충실도가 떨어진다 (2603.17104)
  • 장기 작업에서 에이전트가 자기 코드를 침식한다 (2603.24755)
  • 절차 지시에 동의한 뒤 우회한다 (2605.01771)
  • 인용이 있으면 지어낸 요구사항을 탐지할 수 있다 (2606.30689)
  • 명세가 일차 산출물이다 (2602.00180)

참고 자료: 장편 서사

  • 사후 학습이 주제와 정서와 문체를 평탄화한다 (2605.27878)
  • 결말 예측으로 서사 긴장을 측정한다 (2604.09854)
  • 일관성 오류가 분량에 비례해 늘어난다 (ConStory-Bench)
  • 개고는 문체를 올릴 뿐 정확도는 못 올린다 (2605.13368)
  • 리라이팅이 개인의 목소리를 평준화한다 (2604.22142)
  • 기계 번역에서의 한국어 경어 (LREC 2026)

Q & A

Samchon
https://ttsc.dev