vendange
v0.6.1
Published
Notion → Git spec pipeline engine. 4-layer architecture: Ingest, Validate, Reconcile, Serve.
Maintainers
Readme
Vendange
vendange (fr.) — 포도 수확. 기획문서를 수확해서 개발에 쓸 수 있는 형태로 만든다.
기획문서를 Git 기반 구조화된 마크다운 스펙으로 변환하는 파이프라인 엔진.
- Notion 동기화 — 비개발자가 기획 편집, Vendange가 Git으로 단방향 동기화
- Scaffold — AI 인터뷰 또는 CLI로 스펙 템플릿 직접 생성 (Notion 없이도 가능)
- 버전 관리 — content hash 비교, 변경분만 업데이트, CHANGELOG 자동 생성
- 즉시 접근 — TOON 인덱스로 AI/사람 모두 ID 기반 정확 접근
Problem
| 현재 | 문제 | | ------------------------- | ---------------------------------------------------- | | Notion 기획 페이지가 원본 | AI 접근 시 MCP 호출 → 블록 순회 → 느림 (매번 반복) | | 버전 관리 없음 | 기획 변경 추적 불가, "지난주 뭐 바뀌었지?" 답 없음 | | 의존성 암묵적 | 화면↔데이터↔기능 연결이 사람 머릿속에만 존재 | | 불일치 수동 추적 | "DB에 있는데 기획에 없음" 같은 drift를 수동으로 찾음 |
Architecture
4-Layer Pipeline
Notion (편집기, 유지)
│ vendange sync
▼
┌──────────┐ ┌──────────┐ ┌───────────┐ ┌──────────┐
│ INGEST │──▶│ VALIDATE │──▶│ RECONCILE │──▶│ SERVE │
│ 수집 │ │ 검증 │ │ 대조 │ │ 배달 │
└──────────┘ └──────────┘ └───────────┘ └──────────┘
✅ 구현 ✅ 구현 planned ✅ 구현| Layer | 역할 | 상태 | | ------------- | ---------------------------- | ------- | | INGEST | Notion → 구조화된 마크다운 | ✅ 구현 | | VALIDATE | 문서 간 정합성 검증 + 리포트 | ✅ 구현 | | RECONCILE | 스펙 ↔ 구현 drift 자동 탐지 | planned | | SERVE | TOON 인덱스 + CHANGELOG 생성 | ✅ 구현 |
Dual Interface
사람 (터미널/CI) AI (OpenCode)
│ │
▼ ▼
CLI Plugin
dist/cli.js dist/plugin.js
│ │
└───────────┬───────────┘
▼
코어 엔진
src/core/ (sync, lookup)
src/ingest/ (Notion fetch)
src/serve/ (index, changelog)| Interface | 실행 주체 | 설치 방법 | 용도 |
| ---------- | --------------------------- | ----------------------------------- | --------------------------- |
| CLI | 사람, CI/CD, GitHub Actions | pnpm add -D vendange | 터미널에서 sync/index 실행 |
| Plugin | AI 에이전트 (OpenCode) | opencode.json에 "vendange" 추가 | AI가 도구로 호출, 스펙 조회 |
둘 중 하나만 써도 독립 동작. 코어 엔진은 공유.
How It Works
Pipeline Diagram
┌─────────────────────┐
│ NOTION │
│ (기획자 편집 원본) │
└──────────┬───────────┘
│
════════════════╤══════════════════
Layer 1: INGEST │ (수집 + 구조화) ✅
════════════════╧══════════════════
│
┌───────────────▼────────────────┐
│ Notion Fetcher │
│ • 페이지별 블록 트리 순회 │
│ • H2/H3 기준 파일 분리 │
│ • 볼드 텍스트에서 키워드 추출 │
│ • content hash 변경 감지 │
└───────────────┬────────────────┘
│
┌───────────────▼────────────────┐
│ Markdown + Meta │
│ specs/{category}/ │
│ {SPEC-ID}.md │
│ (frontmatter + content) │
└───────────────┬────────────────┘
│
════════════════╤══════════════════
Layer 2: VALIDATE (스펙 자체 검증) ✅
════════════════╧══════════════════
│
┌───────────────▼────────────────┐
│ Spec Linter (규칙 기반) │
│ │
│ data vs contract 필드 커버리지 │
│ 네이밍 불일치 감지 │
│ enum 값 불일치 감지 + 리포트 │
│ depends_on/graph 정합성 검사 │
└───────────────┬────────────────┘
│
════════════════╤══════════════════
Layer 3: RECONCILE (스펙 ↔ 구현 대조) planned
════════════════╧══════════════════
│
┌───────────────▼──────────────────┐
│ Reconciliation Engine │
│ │
│ 스펙 ↔ DB 스키마 대조 │
│ 스펙 ↔ 라우트/페이지 대조 │
│ 스펙 ↔ API 엔드포인트 대조 │
└───────────────┬──────────────────┘
│
════════════════╤══════════════════
Layer 4: SERVE (배달 + 접근) ✅
════════════════╧══════════════════
│
┌───────────────▼────────────────┐
│ specs/ 폴더 (Git 저장) │
│ + SPEC-INDEX.md (TOON) │
│ + CHANGELOG.md │
└───────────────┬────────────────┘
│
┌───────────────▼────────────────┐
│ AI / 사람 접근 패턴 │
│ │
│ "STU-LIST 개발해" │
│ → SPEC-INDEX에서 탐색 │
│ → depends_on 따라가기 │
│ → 현재 구현 상태 확인 │
│ → drift 있으면 질문: │
│ "스펙에 없는데 DB엔 있음. │
│ 어느 쪽이 맞나?" │
└────────────────────────────────┘INGEST (✅ 구현)
Notion 페이지를 구조화된 마크다운 파일로 변환.
.spec-versions.json으로 content hash 비교 → 변경분만 업데이트- 볼드/코드블록에서 키워드 자동 추출 →
tags필드 - 문서 유형별 ID 패턴 인식 (
STU-LIST,ATT-01,UC-ENR-01등) - H2/H3 기준 파일 분리 + frontmatter 자동 생성
VALIDATE (✅ 구현)
data-definition과 backend-contract 간 불일치를 자동 검증.
vendange lint로 교차 문서 정합성 검사 실행- 규칙:
field-coverage,field-naming,enum-values,spec-dependency spec-dependency:depends_on누락/중복/self 참조/고아 문서/graph 불일치 탐지- 결과를
specs/LINT-REPORT.md로 생성 (엔티티/테이블별 판단 + 권장 액션) vendange sync실행 시 lint도 자동 수행되어 리포트 갱신vendange_lookup은 해당 스펙과 연관된 lint 섹션을 함께 반환
SERVE (✅ 구현)
AI와 사람이 스펙에 즉시 접근할 수 있도록 산출물 생성.
SPEC-INDEX.md— TOON 포맷 전체 인덱스 (path, id, type, deps, status, desc)CHANGELOG.md— 동기화 변경 이력 자동 기록
Quick Start
1. 설치
# npm registry (권장)
pnpm add -D vendangeAlternative (GitHub URL):
pnpm add -D vendange@github:VineyardEdu/vendange2. Plugin (OpenCode)
~/.config/opencode/opencode.json에 추가:
{
"plugin": ["vendange"]
}| Tool | 설명 |
| ----------------- | ---------------------- |
| vendange_sync | Notion → specs/ 동기화 |
| vendange_lookup | ID로 스펙 조회 |
| vendange_list | 전체 스펙 목록 |
| vendange_lint | 문서 간 정합성 검사 |
| vendange_deps | 의존성 그래프 조회 |
3. 실행
vendange sync # Notion → specs/ 동기화
vendange sync --dry-run # 변경분 미리보기
vendange lint # data-definition vs backend-contract 검증
vendange deps # dependency graph 요약Configuration Guide
Notion Integration 설정
Integration 생성
- https://www.notion.so/my-integrations 접속
- "New integration" 클릭
- Internal Integration 생성 → Token 발급
페이지 연결
- 동기화하려는 Notion 페이지 우측 상단
···메뉴 - "Connections" → "Connect to" → 생성한 Integration 선택
- 권한 부여 (Read content)
- 동기화하려는 Notion 페이지 우측 상단
환경 변수 설정
- 프로젝트 루트에
.env파일 생성:
NOTION_TOKEN=ntn_xxxxxxxxxxxxx- 프로젝트 루트에
Notion 페이지 ID 찾기
Notion 페이지 URL에서 추출:
https://www.notion.so/workspace/Page-Title-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
└─────────────────┬──────────────────┘
32자리 hex (ID)UUID 포맷으로 변환:
- 32자리 hex →
8-4-4-4-12패턴으로 하이픈 삽입 - 예:
1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d→1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
Alternative (Notion API):
curl https://api.notion.com/v1/search \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Notion-Version: 2022-06-28" \
-d '{"query": "Page Title"}'.specrc.json 필드 설명
프로젝트 루트에 specs/.specrc.json 생성:
{
"source": {
"type": "notion", // 현재는 "notion"만 지원
"notionVersion": "2022-06-28", // Notion API 버전
"pages": [
{
"name": "screen-definition", // 문서 카테고리 이름 (임의)
"id": "1a2b3c4d-5e6f-7a8b-9c0d-...", // Notion 페이지 UUID
"folder": "screen-definition", // specs/ 하위 폴더명
"splitBy": "h3", // 파일 분리 기준 (h2 | h3 | none)
"docType": "screen", // 문서 타입 (ID 패턴 결정)
},
],
},
"outputs": {
"indexFile": "SPEC-INDEX.md", // TOON 인덱스 파일명
"changelogFile": "CHANGELOG.md", // 변경 이력 파일명
"versionsFile": ".spec-versions.json", // 버전 스냅샷 파일명 (변경 감지용)
},
}전체 예시: examples/specrc-example.json 참조
splitBy 선택 기준
| 값 | 사용 시점 | 예시 |
| ------ | --------------------------------------- | --------------------- |
| h2 | 페이지 내 H2가 개별 항목의 구분자 | 서비스정의서 (도메인) |
| h3 | H2가 카테고리 그룹, H3가 개별 항목 | 화면정의서 (화면) |
| none | 페이지 전체가 하나의 문서 (분리 불필요) | 체크리스트 |
선택 가이드:
- H2마다 개별 spec 파일이 필요하면 →
h2 - H3마다 개별 spec 파일이 필요하면 →
h3 - 페이지 전체가 단일 문서면 →
none
docType 종류 및 ID 패턴
| docType | ID 추출 패턴 | 예시 타이틀 | 추출 ID |
| ------------ | ---------------------------- | --------------------------- | ----------- |
| screen | [A-Z]{3}-[A-Z]+ | STU-LIST: 학생 목록 화면 | STU-LIST |
| feature | [A-Z]{3}-\d{2} | STU-01: 학생 등록 | STU-01 |
| scenario | UC-[A-Z]+-\d{2} | UC-ENR-01: 수강 신청 흐름 | UC-ENR-01 |
| data | H3 코드블록/영문 키워드 추출 | ### Student | Student |
| service | 타이틀 slug 기반 | 학생 관리 서비스 | slug |
| permission | 타이틀 slug 기반 | 관리자 권한 | slug |
| contract | 타이틀 slug 기반 | 학생 조회 API | slug |
| checklist | 타이틀 slug 기반 | 개발 체크리스트 | slug |
| generic | 타이틀 slug 기반 | 일반 문서 | slug |
ID 추출 로직:
screen,feature,scenario: 타이틀에서 정규식 패턴 매칭data: H3 제목 → 코드블록 내용 또는 영문 단어 추출- 나머지: 타이틀 → kebab-case slug 변환
outputs 필드
| 필드 | 기본값 | 설명 |
| --------------- | --------------------- | --------------------------------- |
| indexFile | SPEC-INDEX.md | TOON 인덱스 (전체 스펙 목록) |
| changelogFile | CHANGELOG.md | 동기화 변경 이력 (자동 append) |
| versionsFile | .spec-versions.json | content hash 스냅샷 (변경 감지용) |
모든 파일은 specs/ 폴더에 생성됩니다.
AI Agent Integration
AI 에이전트가 Vendange를 도구로 사용하려면 Skill 문서가 필요합니다.
| Skill | 용도 | 파일 |
| ----- | ---- | ---- |
| Spec Pipeline | sync/lookup/lint 사용 가이드 | examples/skill-template.md |
| Vendange Interview | 소크라테스 인터뷰 → 스펙 결정화 | examples/interview-skill.md |
Interview Skill: AI가 scaffold 템플릿의 빈칸을 기반으로 소크라테스식 질문을 하고, 답변을 모아 구조화된 스펙 파일을 생성합니다. Notion 없이도 스펙 작성 가능.
Engine Structure
vendange/
├── src/
│ ├── cli.ts # CLI 진입점 (얇은 껍데기)
│ ├── plugin.ts # OpenCode Plugin 진입점
│ ├── core/ # 코어 엔진 (CLI + Plugin 공유)
│ │ ├── index.ts
│ │ ├── sync.ts # INGEST + SERVE + VALIDATE 오케스트레이션
│ │ └── lookup.ts # 스펙 조회 + 연관 lint 섹션 병합
│ ├── ingest/ # Layer 1: 수집
│ │ ├── notion-client.ts # Notion API 직접 호출 (재귀적 블록 트리 fetch)
│ │ ├── notion-to-markdown.ts # Notion 블록 → Markdown 변환
│ │ └── splitter.ts # H2/H3 기준 파일 분리 + frontmatter + ID/태그 추출
│ ├── validate/ # Layer 2: 검증
│ │ ├── lint.ts # 교차 문서 린팅 오케스트레이터
│ │ ├── report.ts # LINT-REPORT.md 생성
│ │ └── rules/ # field-coverage, field-naming, enum-values
│ ├── scaffold/ # Spec template generation
│ │ ├── scaffold.ts # 스펙 파일 생성 (frontmatter + 섹션 플레이스홀더)
│ │ ├── templates.ts # doc_type별 템플릿 정의
│ │ └── index.ts # public exports
│ ├── serve/ # Layer 4: 배달
│ │ ├── index-generator.ts # SPEC-INDEX.md TOON 포맷 생성
│ │ └── changelog.ts # CHANGELOG.md 자동 append
│ └── lib/
│ └── config.ts # .env 파싱, .specrc.json 로드, versions 관리
├── examples/
│ ├── skill-template.md # AI Agent Skill 템플릿 (sync/lookup)
│ └── interview-skill.md # AI 인터뷰 → 스펙 결정화 스킬
├── tsup.config.ts # 듀얼 빌드 (dist/cli.js + dist/plugin.js)
├── tsconfig.json
├── package.json
└── README.mdCLI Commands
| 명령어 | 설명 |
| ------------------------------------------------ | -------------------------- |
| vendange sync | Notion → specs/ 동기화 |
| vendange sync --dry-run | 변경분 미리보기 |
| vendange scaffold --type <type> --id <id> | 스펙 템플릿 파일 생성 |
| vendange lint | 문서 간 정합성 검증 |
| vendange deps [id] | 의존성 그래프 조회 |
| vendange help | 명령어 도움말 |
Scaffold Options
vendange scaffold --type <type> --id <id> [options]
Types: data, scenario, screen, feature, contract
Options:
--title <title> Custom title (optional, auto-generated if omitted)
--dep <id> Add dependency (repeatable)
--dry-run Preview without writing예시:
# 엔티티 정의
vendange scaffold --type data --id Refund
# 유스케이스 시나리오 (의존성 포함)
vendange scaffold --type scenario --id UC-PAY-09 \
--title "UC-PAY-09. 환불 계산" --dep Invoice --dep Payment
# 화면 정의
vendange scaffold --type screen --id REF-CALCOutput Structure
specs/ # 소비자 레포에 생성됨
├── .specrc.json # 프로젝트별 설정 (사용자가 작성)
├── .spec-versions.json # 변경 감지 스냅샷 (자동)
├── SPEC-INDEX.md # TOON 인덱스 (자동)
├── CHANGELOG.md # 변경 이력 (자동)
├── LINT-REPORT.md # 문서 정합성 리포트 (자동)
├── AGENTS.md # AI 접근 가이드 (사용자가 작성)
├── service-definition/
│ └── *.md
├── data-definition/
│ └── student.md, class.md ...
├── feature-definition/
│ └── stu-01.md, att-01.md ...
├── screen-definition/
│ └── stu-list.md, cls-detail.md ...
└── ...각 마크다운 파일의 frontmatter:
---
id: STU-LIST
title: "학생 목록 화면"
doc_type: screen
source: notion
notion_page_id: 2e8182a0-...
notion_block_id: abc123
last_synced: 2026-02-10T03:00:00.000Z
notion_last_edited: 2026-02-09T12:30:00.000Z
version: 3
depends_on: []
tags: ["student", "list", "search"]
---Contributing
- 이슈 생성 → 브랜치 생성 → PR
- PR은
main브랜치 대상 - 커밋 메시지는 자유, PR 타이틀이 squash commit 메시지가 됨
License
MIT
