반복된 stale 문제(같은 사실이 여러 곳에 중복 서술)를 근본적으로 줄이는 방법으로 마커 기반 include 도구를 논의 — AsciiDoc tagged include/ markdown-magic 선례 확인 후 build-vs-buy 검토, doc-check.py와 짝인 Python 직접 제작 채택. research/doc-include-plan.md에 플랜 초안(마커 문법, CLAUDE.md 세션 히스토리 파일럿 범위, 열린 질문) 작성 — 세부는 사용자가 다듬을 예정, 구현 착수는 안 함. README.md 색인/CLAUDE.md 백로그·세션 히스토리 동기화.
5.9 KiB
문서 stale 감소용 include 도구 — doc-include.py (가칭)
상태: research — 2026-08-14 세션에 아이디어 확정, 플랜만 초안, 사용자가 다듬을 예정(내일 처리). 구현 착수 전.
배경
같은 날 진행된 코퍼스 전체 사실관계 감사(서브에이전트 4개 병렬)에서 실제
오류 20건을 찾아 고쳤는데, 대부분이 "같은 사실이 두 곳 이상에 적혀있다가
한쪽만 갱신됨" 패턴이었음(bind-system-plan.md 3단계 분할 후 다른 문서가
옛 줄번호를 가리키던 것 11곳 등). 이 프로젝트는 이미 doc-check.py(기계
검증기, ERROR/WARN 리포트)로 이 문제를 사후 탐지하고 있는데, 사용자가
사전 차단(애초에 중복 서술이 안 생기게)이 더 근본적이지 않겠냐고 제안 —
"summary" 같은 블록을 원본 파일에 마커로 표시해두고, 인용하는 쪽은 그 마커
구간을 기계적으로 추출해 붙여넣는 도구를 만들면 정보의 관리 주체가 자연히
한 파일로 모인다는 아이디어.
선례 (재발명 아님을 확인)
- AsciiDoc tagged region include —
// tag::x[]...// end::x[]로 구간 표시,include::file.adoc[tag=x]로 다른 문서가 그 구간만 당겨옴. 사용자가 제안한--#summary-start/--#summary-end아이디어의 원조 격. - markdown-magic(JS) — HTML 주석 마커(
<!-- AUTO-GENERATED-CONTENT:START -->)로 README 등에 다른 파일 내용을 주입, 재실행하면 갱신. Markdown 생태계에서 가장 가까운 기존 도구. - Obsidian/Roam/Logseq의 block transclusion(
![[file#^blockid]]) — 빌드 스텝 없이 렌더 시점에 라이브로 당겨옴. stale이 구조적으로 원천 차단되는 더 강한 버전이지만 이 프로젝트는 정적.md파일이 소스라 뷰어 종속적인 이 방식은 안 맞음.
Build vs Buy 판단 — 직접 제작 채택
- 필요한 기능이 좁음: 마커 사이 텍스트를 원본에서 읽어 대상에 갱신 삽입 +
재실행해도 안정적(idempotent) +
--check모드로 어긋나면 실패. 정규식 몇 개 + 파일 I/O가 전부라 100줄 내외로 충분. - 기존 도구(markdown-magic 등)를 쓰면 이 레포에 없던 Node/npm 툴체인이
새로 들어옴 — 지금 유일한 도구인
doc-check.py가 Python 표준 라이브러리만 쓰는 의존성 0 스크립트라는 관례와 어긋남. 프로젝트가 얻는 이득(TOC 생성, 배지 삽입 등 우리가 안 쓸 기능들)에 비해 대가가 큼. - 마커 문법을 이 코퍼스 관례(한국어,
doc-check.py의 ERROR/WARN 리포팅 스타일)에 맞춰 직접 정하고 싶으므로, 외부 도구 설정 파일로 끼워 맞추는 것보다 직접 짜는 쪽이 코드도 적고 통제도 쉬움.
결론: .claude/tools/doc-check.py와 짝을 이루는 doc-include.py를
Python 표준 라이브러리만으로 신설. --write(갱신 삽입)/--check(어긋나면
ERROR, doc-check.py 파이프라인에 편입) 두 모드.
파일럿 범위 — CLAUDE.md 세션 히스토리부터
사용자가 지목한 이유: 세션 히스토리 항목은 서로 독립적(과거 기록이라 다른 문서가 그 문장을 인용하는 경우가 거의 없음)이라 이 도구가 버그가 있어도 부작용이 다른 곳으로 안 번짐 — 첫 적용 대상으로 가장 안전.
- 지금 구조:
.claude/session/YYYY-MM-DD-NN-slug.md에 세션 원문 전체가 있고,CLAUDE.md의 "세션 히스토리" 절엔 사람이 손으로 압축한 2~4줄 요약 + 링크가 별도로 적혀있음(둘이 물리적으로 분리된 텍스트라 한쪽만 갱신되면 어긋날 수 있음 — 실제로 아직 발생한 적은 없지만 구조적으로 가능한 상태). - 적용 후: 각 세션 파일 안에 "이 요약이 CLAUDE.md에 들어갈 정본"이라고
표시하는 마커 블록을 신설(새로 요약을 쓸 필요 없음 — 지금
CLAUDE.md에 이미 있는 압축 요약을 그대로 그 블록 안으로 옮기면 됨).CLAUDE.md쪽엔 대응하는 include 마커만 남기고,doc-include.py --write가 두 마커 사이 콘텐츠를 세션 파일에서 가져와 채움.
마커 문법 (초안 — 사용자가 확정할 것)
# 세션 파일(.claude/session/2026-08-14-14-....md) 안:
<!--#summary:2026-08-14-14-->
**2026-08-14 열네 번째 세션 — ...** (`session/2026-08-14-14-....md`)
... 2~4줄 압축 요약 ...
<!--#/summary-->
# CLAUDE.md "세션 히스토리" 절 안:
<!--#include:2026-08-14-14 from=session/2026-08-14-14-....md-->
(doc-include.py --write가 여기를 원본 summary 블록 내용으로 갱신)
<!--#/include-->
열린 질문 (사용자가 다듬을 것)
- 마커 문법 자체(위 초안 확정 여부, id 네이밍 규칙 — 날짜+세션번호로 충분한지).
- 기존 세션 항목 전부(13개+)에 마커를 소급 삽입할지, 아니면 다음 세션부터 신규 항목에만 적용하고 과거분은 그대로 둘지.
--write실행 시점 — 수동(세션 마무리 시 사람이 실행) vs 커밋 훅. 이 레포는 지금 CI가 없고 사람이doc-check.py도 수동으로 돌리는 관례라 같은 패턴(수동 + 커밋 전 확인)이 자연스러워 보이지만 확정은 사용자 몫.--check실패를doc-check.py의 ERROR로 편입할지 별도 스크립트로 둘지.- 파일럿이 성공하면 다음 확대 후보 —
.claude/README.md표의 "상태" 요약을 각base//research/문서 맨 위**상태**: ...줄에서 추출해오는 것(단,luau-test/STATUS.md처럼 이미 "폴더 구조 자체가 상태"인 곳은 include로 바꿀 필요 없음 — 그쪽은 이미 소스가 하나로 수렴된 상태라 적용 대상 아님).
우선순위
하 — M0/설계 게이트와 무관한 메타 도구. 사용자가 플랜을 다듬은 뒤 착수 시점 결정.