리스펙스 바우치

작은 결정 규칙에 영수증을 붙입니다. 오프라인에서 점검할 수 있는 기록을 남기고, 규칙을 고친 뒤에는 코퍼스의 차이를 비교합니다.

리스펙스 바우치는 앱을 만드는 틀이 아니라, 앱 안의 작은 결정 규칙에 영수증을 붙이는 방법입니다. 화면도 서버도 데이터베이스도 여기 올리지 않습니다. 나중에 설명해야 할지도 모르는 판단 하나를 작은 리스펙스 규칙으로 떼어 내고, 기록된 답마다 나중에 점검할 수 있는 파일을 남기는 것이 전부입니다. 리스펙스 프로그램을 실행하는 권위는 여전히 레퍼런스 인터프리터에 있습니다.

어떤 질문을 위한 것인가

코드로 내리는 판단 가운데 어떤 것들은 시간이 지나 질문으로 되돌아옵니다.

  • 고객센터에 "이 주문은 왜 자동 환불이 거절됐나요"라는 문의가 들어왔습니다. 석 달 전 규칙과 입력에 대해 어떤 기록이 남았는지 파일로 보여 줄 수 있어야 합니다.
  • 할인율 규칙을 고치려고 합니다. 머지하기 전에, 지난 분기에 처리한 주문 중 어떤 건의 할인율이 새 규칙에서 달라지는지 목록으로 보고 싶습니다.
  • 승인 한도나 접근 판정처럼, 감사나 리뷰에서 "근거를 보여 달라"는 말을 듣는 규칙을 관리하고 있습니다.

이런 규칙은 대개 전체 코드의 아주 작은 조각입니다. 리스펙스 바우치는 그 조각만 맡습니다.

규칙 하나로 따라가기

규칙이라는 말만으로는 크기가 잡히지 않으니 코드로 먼저 보겠습니다. 리스펙스 바우치가 다루는 규칙은 대개 아래 예제 정도를 넘지 않습니다. 배송 후 14일 이내이고 미개봉이면 자동 환불을 승인한다고 합시다.

LISPEX
(define (refund-auto-approved? days-since-delivery opened?)
  (and (<= days-since-delivery 14)
       (not opened?)))

(refund-auto-approved? 9 #f)  ; ⇒ #t

입력은 호스트 애플리케이션이 인자로 넘겨주고 그 값 그대로 고정됩니다. 배송 후 9일에 미개봉이라는 입력을 고정해 평가하면 답은 #t입니다. 리스펙스 바우치 흐름에서는 이 평가가 csk.differential-receipt/v0 형식의 영수증 파일을 남깁니다. 규칙과 고정된 입력, 그리고 답을 해시로 함께 기록한 파일입니다. 영수증을 규칙 옆에 두고 함께 커밋하면, 석 달 뒤 "왜 그때 그렇게 답했나"라는 질문을 기억이 아니라 파일에서 시작할 수 있습니다. 다만 영수증은 기록이지 증명이 아닙니다. 평가 시점에 적힌 내용을 보여줄 뿐이고, 그 신뢰도는 영수증을 만든 과정에 달려 있습니다. v1.3.4부터는 네이티브 단독 실행 바이너리가 공개 영수증 생성 경로입니다.

이 규칙은 지금 바로 플레이그라운드에 붙여 넣어 평가해 볼 수 있습니다. 어떤 판단을 규칙으로 떼어 낼지 고르는 기준과 더 현실적인 예제는 결정 규칙 작성하기 가이드에서 다룹니다.

바우치 명령이 답하는 질문

lispex diff-receipt --input <datum-file> <rule.lspx>는 네이티브 단독 실행 바이너리에서 영수증을 생성합니다. 규칙을 고정된 데이터에 대해 평가하고 csk.differential-receipt/v0 JSON을 표준 출력에 씁니다.

BASH
lispex diff-receipt --input inputs/refund-2026-03-0412.datum rules/refund.lspx > receipts/refund-2026-03-0412.json

lispex verify <receipt>는 영수증 파일이 그 자체로 앞뒤가 맞는지 검사합니다. 스키마를 확인하고, 영수증에 담긴 해시를 다시 계산하며, --source 옵션을 주면 로컬 규칙 파일이 기록된 소스 해시와 일치하는지도 확인합니다. 문의 대응, 감사 준비, 인수인계처럼 오래된 영수증을 다시 꺼내 보는 상황에서 파일이 변형되지 않았는지 확인할 때 실행합니다. 네트워크도 별도 서비스도 필요 없이 오프라인으로 동작합니다. 다만 평가를 다시 실행하지는 않으며, 영수증이 애초에 정직하게 만들어졌는지, 결정을 누가 언제 적용했는지는 알려주지 못합니다. 검사를 통과했다는 것은 파일이 스스로 일관되고 지정한 규칙 텍스트와 맞는다는 뜻일 뿐입니다.

BASH
lispex verify receipts/refund-2026-03-0412.json

lispex replay <corpus> --against <version-or-receipts-dir>는 "규칙을 고치면 과거 답 중 무엇이 달라지나"에 답합니다. 규칙 변경을 머지하기 전에 실행합니다. 커밋된 결정 코퍼스를 버전 핀이나 영수증 디렉터리와 비교해서 어떤 답이 달라졌는지 목록으로 보고합니다.

BASH
lispex replay decisions/refund --against receipts/2026-Q1

영수증이 말해 주는 것과 말해 주지 않는 것

영수증은 특정 규칙과 고정된 입력, 기록된 답을 하나의 파일로 묶고 그 기록을 해시에 연결합니다. 기록된 아티팩트들이 서로 어긋나지 않는지는 보여 줄 수 있습니다. 다만 영수증이 정직하게 만들어졌는지, 실제 시스템이 그 답대로 고객을 처리했는지, 언제 누가 적용했는지는 말해 주지 않으며, 사람의 검토를 대신하지도 않습니다. 그런 일은 서명, 타임스탬프, 배포, 리뷰라는 별도의 계층이 다룹니다.

npm으로 설치하는 verifyreplay는 공개 규격 아티팩트를 검사하는 도구입니다. 바이트와 해시를 확인할 뿐, 리스펙스 소스를 실행하지 않으며 레퍼런스 인터프리터를 대체하지 않습니다.

검사 가능한 부분집합의 조건

이 흐름이 성립하려면 같은 규칙에 같은 입력을 주었을 때 언제나 같은 답이 나와야 합니다. 그래서 리스펙스 바우치는 리스펙스를 좁게 닫아 둔 부분집합 위에서만 동작합니다.

  • 문법은 R7RS 계보를 따르는 고정된 폼만 씁니다. 매크로도 숨은 상태도 없습니다.
  • 내장 프로시저가 고정되어 있고, 입력은 호스트가 명시적으로 바인딩합니다. 규칙이 스스로 데이터를 가져오지 않습니다.
  • 영수증을 비롯한 산출물은 바이트 단위로 고정된 JSON 규약을 따릅니다.

이 조건 밖의 리스펙스 코드도 얼마든지 실행할 수 있습니다. 다만 영수증이라는 약속은 이 부분집합 안에서만 유효합니다.

지금 할 수 있는 것과 준비 중인 것

  • 규칙 자체는 지금 바로 플레이그라운드에서 평가해 볼 수 있습니다.
  • 네이티브 단독 실행 바이너리는 lispex diff-receipt로 영수증을 생성합니다.
  • npm install -g lispex로 설치하는 CLI는 lispex run으로 파일을 실행하고, lispex verifylispex replay로 기존 영수증과 코퍼스를 검사합니다. 영수증은 생성하지 않습니다. 명령 예시는 시작하기에 있습니다.
  • 브라우저 플레이그라운드는 스니펫 실행 전용입니다. 영수증은 생성하지 않습니다.
  • 공개 미러와 릴리스 번들에는 examples/vouch-loop가 포함됩니다. 비공개 저장소 없이 생성, 검증, 리플레이를 한 번에 실행해 볼 수 있는 한 규칙짜리 코퍼스입니다.