| name | meeting-minutes |
| description | 회의 녹음/텍스트 노트에서 구조화된 회의록을 마크다운 정본 + PDF(Pretendard) + Google Docs 3산출물로 자동 생성한다. 산출물은 프로젝트 meetings/<YYYYMMDD_제목>/ 폴더에 1차 정본으로 저장한다. "회의록 만들어", "회의록 작성", "미팅 정리", "녹음 파일 분석", "회의 정리", "회의 내용 정리", "STT 변환", "화자분리", "액션아이템 추출", "미팅 요약" 같은 요청, 또는 녹음 파일 경로 (.m4a/.wav/.mp3)나 회의 텍스트 노트가 주어지면 다른 도구로 직접 처리하지 말고 반드시 이 스킬을 사용하라. 회의록을 만든 뒤 발송까지 요청되면 이 스킬이 meeting-mail 스킬을 이어서 호출한다. |
Meeting Minutes — 회의록 제작 스킬
비유: 회의를 받아 적는 전담 서기. 녹음이든 메모든 받아서, 누구나 읽기 쉬운 정식 회의록으로 정리하고, 인쇄용 PDF와 공유용 Google Docs까지 만들어 회의 폴더에 가지런히 보관한다.
회의 입력(녹음 파일 경로 또는 텍스트 노트)을 받아 마크다운 정본 → PDF(Pretendard) → Google Docs 3산출물을 만들고, 프로젝트 meetings/<YYYYMMDD_제목>/ 폴더에 저장한다. 무거운 STT·화자분리는 기존 자산을 재사용하고, 이 스킬은 회의록 구조화 + 2포맷 변환 + 저장 + (선택) 발송 체이닝을 책임진다.
핵심 원칙
- 마크다운이 정본(SSOT). PDF·Google Docs는 마크다운에서 파생한다.
- 프로젝트
meetings/<날짜_제목>/가 1차 정본 (글로벌 ~/meeting-automation/ 출력 폴더에 산출물을 남기지 않는다 — data-policy.md /meeting 예외).
- 실재하는 명령만 사용. 없는 경로/명령을 가정하지 않는다 (
~/meeting-automation/는 미설치일 수 있으므로 Step 1에서 존재를 확인하고 폴백).
- 결론 먼저: 회의록 요약 3줄을 맨 앞에 둔다.
번들 스크립트 (이 스킬 폴더의 scripts/)
이 스킬의 base directory를 $SKILL_DIR이라 하자 (스킬 로드 시 안내되는 절대경로 = $HOME/팀클코/.claude/skills/meeting-minutes). 아래 두 스크립트는 매번 인라인으로 재작성하지 말고 그대로 호출한다.
$SKILL_DIR/scripts/create_gdoc.py — Google Docs 생성 + gws 출력 오염 방어 파싱(헤더 줄/제어문자) 내장. Step 4에서 사용.
$SKILL_DIR/scripts/make_image_pdf.py — 텍스트 PDF → 이미지 PDF(폰트 0). Step 3.5 선택 단계에서 사용.
회의록 마크다운 표준 구조는 $SKILL_DIR/references/minutes-template.md에 있다. Step 2에서 참조한다.
Step 0 — 입력 분류 + 저장 폴더 생성
입력을 두 갈래로 분류한다.
- (A) 음성 파일 경로(
.m4a/.wav/.mp3) → Step 1a (STT)
- (B) 텍스트 노트(붙여넣은 텍스트 또는
.txt/.md 경로) → Step 1b (STT 건너뜀)
날짜·제목을 정하고 저장 폴더를 만든다. 날짜는 암산하지 말고 date로 구한다.
DATE=$(date +%Y%m%d)
TITLE="<회의제목_kebab_또는_한글>"
OUTDIR="$(pwd)/meetings/${DATE}_${TITLE}"
mkdir -p "$OUTDIR"
echo "저장 폴더: $OUTDIR"
Step 1a — STT (음성 입력일 때만)
기존 STT 파이프라인을 존재 확인 후 사용한다. 없으면 폴백한다.
if [ -d "$HOME/meeting-automation" ] && [ -f "$HOME/meeting-automation/process_meeting.py" ]; then
echo "STT 파이프라인 발견 — 실행"
WORK_DIR="$OUTDIR/work"; mkdir -p "$WORK_DIR"
python3 "$HOME/meeting-automation/process_meeting.py" "<음성파일경로>" "$WORK_DIR"
else
echo "주의: ~/meeting-automation 파이프라인이 설치되지 않았습니다. 폴백을 선택하세요."
fi
- 폴백 (a): 글로벌
meeting-secretary 에이전트가 존재하면 Agent 도구(subagent_type: meeting-secretary)로 STT·화자분리를 위임하고 반환된 전사를 Step 2로 잇는다.
- 폴백 (b): 음성을 못 푸는 상황이면 사용자에게 "전사 텍스트를 붙여 주세요"라고 요청하고 Step 1b로 전환한다.
- STT 실패/파이프라인 부재를 회의록 생성 실패로 종결하지 말 것 — 항상 텍스트 노트 경로로 진행 가능하다.
Step 1b — 텍스트 노트 정리 (STT 건너뜀)
붙여넣은 텍스트(또는 .txt/.md)를 읽어 발화 흐름을 정리한다. 화자 라벨이 있으면 보존한다.
Step 2 — 마크다운 회의록 작성 (정본)
$SKILL_DIR/references/minutes-template.md의 표준 구조로 전사/노트를 정리해 $OUTDIR/minutes.md에 Write로 저장한다. 결론(요약 3줄)을 맨 앞에 둔다.
Step 2.5 — 일정 자동 등록 (의무 + 분류기 게이트 인지)
회의록에 다음 회의·마감·후속 미팅 + 시각이 명시되면, 되묻지 말고 즉시 gws calendar +insert로 Google Calendar에 등록한다(data-policy.md Calendar 의무). 업무 일정은 primary(생략), 개인 키워드면 개인 캘린더 ID. 시간 미확정이면 description에 "(시간 미확정)".
gws calendar +insert --summary '[회의] 후속 미팅' \
--start '2026-07-01T10:00:00+09:00' --end '2026-07-01T11:00:00+09:00' \
--description '안건: ...'
분류기 게이트 (학습 교훈 — 우회 금지): "회의록만" 요청한 맥락에서는, 회의록 본문에서 시각을 추론해 만든 캘린더 이벤트가 Claude Code auto-mode 권한 분류기에 의해 [External System Writes]로 거부될 수 있다(사용자 메시지가 캘린더를 명시 요청하지 않았다고 판단). 이는 정상 분기다 — 무리하게 우회하지 말 것. 거부된 일정은 회의록 본문/links.txt에 그대로 남겨 추적 가능하게 두고, 최종 보고에 "캘린더 N건 등록, M건 거부(사유)"를 명시한다. 시각 미확정 마감을 09:00 등 임의 시각으로 가설 등록하면 거부 트리거가 높아진다 — 확정 시각이 있는 일정은 통과율이 높다. 사용자가 "일정도 등록해줘"라고 명시하면 분류기가 통과시킨다.
Step 3 — DOCX + PDF 변환 (Pretendard 강제)
마크다운 정본을 글로벌 변환 스크립트 md-to-docx/convert.py로 DOCX+PDF로 만든다. 이는 Skill이 아니라 Bash로 실행하는 스크립트다(set_korean_font/enforce_fonts/postprocess_zip_fonts 3단으로 Pretendard를 ascii/hAnsi/eastAsia/cs 4속성에 강제). 9종 Pretendard OTF가 ~/Library/Fonts/에 설치돼 LibreOffice가 임베드한다.
python3 $HOME/qjc-office/dotclaude/scripts/md-to-docx/convert.py \
"$OUTDIR/minutes.md" --pdf
정확한 인자(--pdf/--out 등)는 실행 전 python3 .../convert.py --help로 확인한다.
Step 3.5 — PDF 폰트/렌더 검증 (harness Read 금지)
PDF는 weasyprint가 아니라 LibreOffice 경유라 라틴 기호 누락 위험은 낮지만, 검증은 harness Read가 아니라 사용자 실제 렌더러(Quick Look)로 한다(html-to-pdf-fonts.md 교훈).
pdffonts "$OUTDIR/minutes.pdf"
qlmanage -t -s 1600 -o "$OUTDIR" "$OUTDIR/minutes.pdf" 2>/dev/null
echo "검증: $OUTDIR/minutes.pdf.png 에서 한글/특수문자(%, ₩, →) 정상 표시 확인"
- 비-Pretendard 폴백(Carlito/AppleSDGothicNeo/Symbol)이 보이거나 글리프가 깨지면, 미커버 글리프(한자 등)를 회피하거나 변환을 재시도한다.
- (선택) 모든 뷰어에서 동일하게 보이는 이미지 PDF가 필요하면(외부 발송 등) 번들 스크립트를 쓴다:
python3 "$SKILL_DIR/scripts/make_image_pdf.py" --pdf "$OUTDIR/minutes.pdf"
Step 4 — Google Docs 생성 (공유 링크용)
마크다운 본문으로 Google Docs를 만든다. 번들 스크립트를 사용한다 — gws 출력 오염(keyring 헤더 줄 + 제어문자)을 방어하는 안전 파서가 내장돼, 인라인 파이프의 조용한 실패(빈 documentId → 중복 빈 문서 양산)를 막는다.
DOC_JSON=$(python3 "$SKILL_DIR/scripts/create_gdoc.py" \
--title "[회의록] $TITLE $DATE" --markdown-file "$OUTDIR/minutes.md")
echo "$DOC_JSON"
DOC_URL=$(printf '%s' "$DOC_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin)['url'])")
Google Docs 폰트 제약 (명시)
Google Docs는 API로 폰트를 강제 지정할 수 없고 클라이언트가 렌더한다. 수신자 환경에 Pretendard가 없으면 폴백(Noto Sans/Arial)된다. 따라서 **정확한 한글 타이포의 정본은 PDF(minutes.pdf / minutes-final.pdf)**이고, Google Docs는 편집·공유 링크용이다.
Step 5 — 저장 정리 + 산출물 반환
cat > "$OUTDIR/links.txt" <<EOF
markdown: $OUTDIR/minutes.md
pdf: $OUTDIR/minutes.pdf
pdf_img: $OUTDIR/minutes-final.pdf (있으면)
gdocs: $DOC_URL
EOF
ls -lh "$OUTDIR"
- git repo면 음성 원본은
.gitignore로 제외하고 gdrive:// 경로만 마크다운에 참조한다. 텍스트/PDF는 커밋 가능.
- 메인 세션에 결론 먼저로 반환: 회의록 요약 3줄 + 산출물 절대경로(폴더) + Google Docs URL + (있으면) 캘린더 등록/거부 건수.
Step 6 — (선택) 발송 체이닝
사용자가 "발송"/"메일 보내"를 요청하거나 회의록 생성과 함께 발송이 지시된 경우에만, Skill 도구로 meeting-mail 스킬을 이어서 실행한다. 스킬은 메인 세션 인라인 실행이므로 직전 산출물 경로가 그대로 공유된다 — meeting-mail에 다음을 그대로 넘긴다.
- PDF:
$OUTDIR/minutes-final.pdf(있으면) 또는 $OUTDIR/minutes.pdf
- Google Docs URL:
$DOC_URL
- 제목·날짜:
$TITLE / $DATE
- 수신자 미지정 시
meeting-mail 기본값(recipient@example.com) 사용
meeting-mail은 외부 발송이라 미리보기 → 사용자 명시 승인 게이트를 자체 통과한다. 이 스킬은 발송을 강제하지 않는다(요청 없으면 산출물 경로만 반환).
금지 패턴
- ❌ 글로벌
~/meeting-automation/meeting-output/에 산출물 고립 (프로젝트 폴더 1차 정본 위반)
- ❌
harness Read로 PDF 깨짐 검증 (시스템 폰트로 항상 정상 표시 — qlmanage/pdffonts 사용)
- ❌ 존재하지 않는 명령/경로 호출 (실행 전
--help·test -f로 확인)
- ❌ Google Docs 생성 시 인라인 파이프로 documentId 파싱 (번들
create_gdoc.py 사용 — 빈 ID/중복 빈 문서 방지)
- ❌ 캘린더 분류기 거부를 무리하게 우회 (Step 2.5 게이트 — 거부는 정상 분기, 보고에 명시)
- ❌ 요청 없는 자동 메일 발송 (Step 6는 명시 요청 시에만)