/rɪˈsiːts/ — "receipts"로 발음. 의도적인 스펠링. (한국어 ㄹ이 R·L 양쪽으로 매핑되는 걸 브랜드로 삼음.)
English version: README.md
모든 완료 주장은 leceipts가 필요하다.
코드 변경 작업이 구조화된 검증 보고서로 끝나도록 강제하는 경량 툴킷. 검증을 필수 섹션으로 만들어서 "다 됐어요" 거짓말을 구조적으로 막는다.
AI 코딩 어시스턴트(Claude, Cursor, Copilot, Codex)를 쓰는 모든 팀이 부딪히는 벽:
사람: "로그인 버그 고쳐줘"
AI: "완료했습니다! 로그인 버그를 수정했고, 모든 것이 정상 작동합니다."
(돌려본다. 여전히 터진다.)
AI가 악의로 거짓말하는 게 아니다. 검증이 실제로 일어났음을 증명해야 하는 구조적 자리가 없어서 거짓말을 한다. "정직해줘"라고 부탁하면 yes 라고 답하고 계속 거짓말을 한다. "검증" 섹션이 필수인 응답 형식을 주면, 그 순간 거짓말이 구조적으로 드러난다 — 빈 검증 칸은 누가 봐도 빈칸이니까.
같은 실패는 사람에게도 일어난다. "좋아보여, 머지해" PR에서 실제로는 아무도 테스트를 안 돌린 케이스.
이 킷은 둘 다 한 가지 메커니즘으로 해결한다: 모든 코드 변경이 따라야 하는 5단 응답 형식 + 영속화된 리포트 파일의 구조를 강제하는 standalone 체커.
1. 문제 원인 — 실제로 뭐가 왜 잘못됐나
2. 수정 내용 — 어떤 파일/라인을 바꿨나
3. 재발 방지 — 이 버그가 다시 조용히 안 나게 만드는 조치
4. 검증 결과 — 실행한 명령 + 실제 결과
5. 남은 리스크 — 회귀 가능성과 미검증 영역 (wishlist 금지)
끝. 스키마 없음, YAML front-matter 없음, 쓰기 위한 툴링 없음. AI든 사람이든 순수 마크다운으로 쓸 수 있고, 체커가 매 커밋마다 구조를 검증한다.
| 섹션 | 막는 것 |
|---|---|
| 1. 원인 | "바꿨더니 되네" — 왜 망가졌는지 모르고 고친 건 보통 증상 패치 |
| 2. 수정 | 조용한 범위 확장 — 무엇을 건드렸는지 명시적 리스트 강제 |
| 3. 재발 방지 | 진짜 fix로 위장한 핫픽스 — 가드레일·테스트·"의도적 생략" 강제 |
| 4. 검증 | 핵심 거짓말: "테스트했어요"인데 증거 없음 — 명령 + 결과 강제 |
| 5. 남은 리스크 | 과신 — 검증 못 한 것에 대한 정직한 공개 강제 |
5번 칸엔 역설적인 룰이 있다: wishlist가 아니다. 회귀 가능성과 미검증 영역만. "더 강화하면 좋을 것", "후속 개선" 같은 wishlist 항목은 그대로 두면 5번 칸이 무한히 커져서 모든 리포트가 미완 같아 보이므로, 체커가 wishlist 표현을 룰 위반으로 잡는다.
필요함 — 다음 중 하나라도:
불필요함:
습관이 되면 코드 변경 보고당 약 30초 추가. 비용은 작고 잡아내는 건 크다.
┌────────────────────────────────────────┐
│ 1. AI/사람이 5단 리포트를 작성 │
│ 마크다운 파일 또는 PR 본문에 │
└─────────────────┬──────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 2. 영속화하는 경우: 파일이 │
│ plans/<티켓>-verification- │
│ report.md에 저장됨 │
└─────────────────┬──────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 3. CI에서 check-reports.ts 실행: │
│ - 구조: 5개 섹션 모두 존재 │
│ - 내용: 3/4번 섹션 비어있지 않음 │
│ - 내용: 5번 섹션이 wishlist 아님 │
└─────────────────┬──────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 4. 위반 시 merge 차단 │
│ clean 리포트는 merge 허용 │
└────────────────────────────────────────┘
세 가지 레이어:
docs/working-rules.md) — AI/사람이 읽고
따르는 룰. CLAUDE.md 등에 박는다.templates/verification-report-template.md) —
티켓/변경 단위로 영속화되는 파일 포맷.scripts/check-reports.ts) — CI에서 자동 실행되어
위반 시 머지를 막는 자동 검사.필요한 부분만 골라 채택 가능. 프롬프트 레이어만으로도 응답 품질이 즉시 올라감. 산출물 레이어를 추가하면 리포트가 검색·감사 가능. 강제 레이어까지 가면 전체가 치트 방지됨.
npm install --save-dev leceipts tsx
leceipts는 TypeScript 소스로 배포되고 tsx로 실행되므로 tsx도
devDependency로 같이 설치해야 한다. 둘 다 dev 전용이라 런타임 번들에
전혀 영향 없음.
설치 확인:
npx tsx node_modules/leceipts/scripts/check-reports.ts --help 2>&1 || true
패키지 페이지: npmjs.com/package/leceipts
본인 프로젝트 루트에:
// verification-kit.config.json
{
"reportsDir": "plans",
"reportPattern": "-verification-report\\.md$",
"legacyMarker": "",
"baseBranch": "main"
}
reportsDir — 검증 리포트가 저장될 폴더reportPattern — 체커가 인식할 파일명 정규식legacyMarker — 구 포맷 리포트를 grandfather 하는 HTML 코멘트baseBranch — 기본 "신규 리포트만 검사" 모드가 사용하는 브랜치mkdir -p plans
cp node_modules/leceipts/templates/verification-report-template.md \
plans/verification-report-template.md
docs/claude-md-snippet.md을 보고 적절한
스니펫을 본인의 CLAUDE.md / AGENTS.md / .cursorrules에 박으세요.
이게 AI 코딩 어시스턴트가 5단 형식을 자동으로 사용하게 만든다.
전체 룰 문서는 docs/working-rules.ko.md를 본인 프로젝트(docs/working-rules.ko.md)로
복사해서 CLAUDE.md에서 참조.
npx tsx node_modules/leceipts/scripts/check-reports.ts \
--config ./verification-kit.config.json
새 설치면 no reports to check가 나온다(아직 리포트 없음). 이 명령을
CI에 추가:
# .github/workflows/ci.yml
- name: Check verification reports
run: npx tsx node_modules/leceipts/scripts/check-reports.ts \
--config ./verification-kit.config.json
{
"scripts": {
"check:reports": "tsx node_modules/leceipts/scripts/check-reports.ts --config ./verification-kit.config.json"
}
}
이제 npm run check:reports 하나로 사람도 CI도 같이 쓴다.
이미 구 포맷으로 쓴 리포트가 있으면 각 파일 맨 위에 이 줄을 추가해서 체커가 스킵하게 만든다:
one-liner:
for f in plans/*-verification-report.md; do
if ! grep -q "legacy-verification-report" "$f"; then
{ echo ""; cat "$f"; } > "$f.tmp" && mv "$f.tmp" "$f"
fi
done
체커는 이 마커가 없는 리포트에만 구조를 강제하므로 히스토리 마이그레이션이 필요 없음.
각 리포트에 대해 2-pass 검사:
모든 리포트는 5개 섹션 헤딩을 모두 가져야 한다 (한글/영문 모두 허용).
[leceipts] FAIL — 1 report(s) have violations:
plans/TASK-042-verification-report.md
- 3. Recurrence prevention / 재발 방지
- 5. Remaining risk / 남은 리스크
존재하는 섹션은 비어있거나 placeholder만 있으면 안 된다:
[leceipts] FAIL — 1 report(s) have violations:
plans/TASK-042-verification-report.md
- 3. Recurrence prevention — empty or placeholder-only body
- 4. Verification — no command, result marker, or 'unverifiable' statement found
- 5. Remaining risk — wishlist phrasing detected: 후속 개선, 더 강화 (see working-rules.md §7)
tsx scripts/check-reports.ts # 신규 리포트만 검사 (기본)
tsx scripts/check-reports.ts --all # 모든 리포트 검사
tsx scripts/check-reports.ts --file <경로> # 특정 파일만 검사
tsx scripts/check-reports.ts --config <경로> # 기본이 아닌 config 위치
기본 "신규 리포트만" 모드는 git ls-tree <baseBranch>로 base branch에
아직 없는 리포트를 찾는다. CI가 historical 리포트를 플래그하지 않고
신규 작업에만 구조를 강제할 수 있다.
git clone <이 저장소>
cd leceipts
npm install
# example 리포트 검사 — 통과해야 함
npm run example:check
# → [leceipts] OK — 1 report(s) checked, all passed
# --all 모드
npm run example:check:all
그리고 example/plans/TASK-001-example-verification-report.md를 보면
잘 쓴 리포트가 어떻게 생겼는지 확인 가능.
- name: Check verification reports
run: npx tsx node_modules/leceipts/scripts/check-reports.ts \
--config ./verification-kit.config.json
# .git/hooks/pre-commit
#!/usr/bin/env bash
set -e
npx tsx node_modules/leceipts/scripts/check-reports.ts \
--config ./verification-kit.config.json
이미 scripts/verify-build.sh 같은 게 있으면:
#!/usr/bin/env bash
set -euo pipefail
npm run typecheck
npm test
npm run build
# 이 줄 추가:
npx tsx node_modules/leceipts/scripts/check-reports.ts \
--config ./verification-kit.config.json
기본 체커는 -verification-report\.md$ 매칭 파일을 찾는다. config에서
reportPattern 변경:
{
"reportsDir": "docs/verify",
"reportPattern": "^VR-\\d+\\.md$"
}
{ "baseBranch": "develop" }
체커는 기본적으로 한국어와 영어 헤딩을 받는다. 제3 언어를 지원하고 싶으면
scripts/check-reports.ts의 REQUIRED_SECTIONS를 포크해서 패턴 추가.
PR 환영.
구조 검사(Pass 1)만 원하고 내용 검사(Pass 2)는 원치 않으면 스크립트를 포크해서 Pass 2 블록 제거. 구조 검사만으로도 의미 있는 품질 게이트가 됨.
킷을 작게 유지하려고 의도적으로 뺀 것들:
위가 필요하면 스크립트가 약 300줄이라 wrap하기 쉽다.
이 킷은 AI 전용이 아니다. 작동 대상:
이 킷은 오직 코드 변경 검증 하나에 집중한다. 생성 콘텐츠 품질, 프롬프트 관리, 기타 인접 문제를 풀려 하지 않는다.
Q: PR 설명을 대체하나? A: 아니 — 보완한다. 5단 형식은 PR 설명 안에 살거나 별도 파일로 살 수 있다. 대부분 팀은 둘 다: 파일은 정식 기록, PR 설명은 요약.
Q: 1줄 오타 수정 같은 사소한 변경이면? A: 섹션 4는 여전히 적용 — "Typecheck: 통과, Tests: 통과". 섹션 1-3은 한 줄씩이면 됨. 섹션 5는 "해당 없음". 오버헤드 약 30초이고 실제 회귀는 여전히 잡힘.
Q: 영속 리포트 파일 없이 쓸 수 있나? A: 예. 5단 형식은 채팅 답변이나 PR 설명에만 살 수도 있다. 그 경우 체커는 선택 사항이 됨 — 체커의 역할은 영속화된 파일의 구조를 강제하는 것.
Q: AI 어시스턴트가 형식을 자꾸 잊어요. 어떻게?
A: 두 가지. 첫째, 룰을 CLAUDE.md / AGENTS.md / .cursorrules의
최상단에 박기 — 서브 문서에 묻지 말고. 둘째, 체커를 CI에 추가해서 AI가
섹션을 빠뜨리면 즉시 피드백이 돌아오게. 몇 번 반복하면 형식이 자동화됨.
Q: TypeScript, Python, Rust, Go에서 작동하나? A: 예 — 킷의 스크립트는 TypeScript(tsx)이지만 워크플로우는 언어 중립. 본인 프로젝트는 어떤 언어든 괜찮고, 체커 스크립트만 Node 18+ 필요. CI에 Node를 넣고 싶지 않으면 본인 언어로 체커 재작성하면 됨 — 300줄 미만이고 filesystem + regex만 씀.
Q: Conventional Commits / Semantic PR과 비교하면? A: 다른 축. Conventional Commits는 제목 줄을 표준화하고, 이 킷은 검증 내러티브를 표준화한다. 함께 써도 됨.
Q: Python 버전 체커 있나? A: 아직. 리포트 파일 포맷은 언어 중립(순수 마크다운)이라 Python 포팅이 간단함. PR 환영.
MIT — LICENSE 참조.
ivan (@0oooooooo0)이 만들었다.
$ claude mcp add leceipts \
-- python -m otcore.mcp_server <graph>