docs-sync · diff
git:20260822.8e0b825 to git:20261024.c5b81d9
139 added, 50 removed. Audit A to A.
---
name: docs-sync
- description: 코드·설정·프리셋 변경 뒤 문서를 현행화한다. "문서 현행화", "README 갱신", "문서 최신화" 요청 시, 그리고 동작·경로·버전·수치를 바꾼 PR 을 올리기 직전에 사용. 문서의 주장을 실제 코드·명령 출력·공식문서와 대조해 정정하고, 다국어 짝 파일을 함께 갱신한다.
- user-invocable: true
- allowed-tools: Bash, Read, Grep, Glob, Edit, Write
+ description: 문서 현행화(docs-sync) — 코드·구성이 바뀐 뒤(디렉터리 삭제·이동, 포트·명령·의존성 변경, 큰 리팩터링 머지) 에이전트 지침(AGENTS.md·CLAUDE.md)·README·규칙(.claude/rules)·스킬·docs 가 실제와 어긋난 곳을 찾아 고친다. 지워지거나 옮겨진 경로를 가리키는 참조를 스크립트로 뽑고, 현행 지시와 시점 기록을 갈라 현행만 고친다. "문서 현행화", "문서 최신화", "README 갱신", "문서 드리프트 확인", "docs-sync", "남은 참조 정리" 요청과, 동작·경로·버전·수치를 바꾼 PR 을 올리기 직전에 쓴다. 문서의 주장을 실제와 대조하고 다국어 짝 파일을 함께 고친다. 메모리 감사는 memory-factcheck, AGENTS.yaml 세팅은 yd-agents-yaml 이 맡는다.
---
- # 문서 현행화 (docs-sync)
+ # docs-sync
- 문서 stale 은 **자동 게이트에 걸리지 않는다.** 링크 체커는 깨진 링크만 보고, 테스트
- 스위트는 문서를 읽지 않는다. 그래서 절차로 잡는다.
+ 코드는 빌드와 테스트가 지켜 주지만 문서는 아무도 지켜 주지 않는다. 디렉터리를
+ 지우거나 옮기면 그 경로를 가리키던 지침·README·규칙이 조용히 거짓이 된다.
+ 에이전트는 그 문서를 읽고 없는 파일을 찾거나 지운 명령을 다시 돌린다.
+ 이 스킬은 **바뀐 실제에 문서를 맞춘다**. 판단 기준은 언제나 코드·설정·파일시스템과
+ 실제 실행 결과다. 문서끼리 맞추는 것이 아니다.
+
## 원칙
- **주장 단위로 검증한다.** 문서를 "읽고 자연스러운지" 보는 게 아니라, 문장이 담은
**검증 가능한 주장**(경로·버전·수치·동작·기본값)을 뽑아 실제와 대조한다.
- **근거 없이 고치지 않는다.** 파일:라인, 명령 출력, 공식문서 URL 중 하나가 있어야 한다.
확인 못 한 건 지우지 말고 **"미검증"으로 명시**한다 — 조용히 삭제하면 정보가 사라진다.
- **낙관적 서술 금지.** 부분만 동작하면 "동작한다"고 쓰지 않는다. 되는 범위와 안 되는
범위를 나눠 쓴다.
- ## 절차
+ ## 경계
- ### 1. 변경 범위 추출
+ | 대상 | 맡는 스킬 |
+ |---|---|
+ | 에이전트 영속 메모리의 사실 감사 | `memory-factcheck` (이 스킬은 경로 참조만 같이 고친다) |
+ | `AGENTS.yaml` 처음 세팅·구조 변경 | `yd-agents-yaml` (이 스킬은 기존 값이 실제와 맞는지만 본다) |
+ | 프로젝트 전용 대조표 | 레포에 `*-doc-sync` 같은 프로젝트 스킬이 있으면 **그 대조표를 먼저** 따른다 |
+ | 고친 문장·보고서·이슈/MR 본문의 문장 정리 | `yd-writer-kr` (이 스킬은 무엇을 고칠지 정하고, 문장은 그 규칙으로 쓴다) |
+ | 이슈·커밋·MR | 레포 워크플로(AGENTS.md). GitLab 에이전트 계정을 쓰면 옵트인 `yd-git-ship` |
+ ## 워크플로
+
+ ### 1. 범위 정하기
+
+ 무엇이 바뀌었는지부터 확정한다. 추측으로 범위를 넓히지 않는다.
+
```bash
- git log --oneline <last-doc-commit>..HEAD
- git diff --stat <last-doc-commit>..HEAD
+ git log --oneline -15 # 기준점 찾기
+ git diff --name-status -M <기준> HEAD | head # 무엇이 지워지고 옮겨졌나
```
- 문서에 영향 주는 변경만 추린다 — CLI 플래그·기본값, 파일/디렉터리 경로, 생성 산출물,
- 버전, 임계값·수치, 게이트 동작, 지원 범위.
+ - 기준점은 사용자가 말한 커밋·MR, 없으면 문서를 마지막으로 맞춘 머지 직전 커밋이다.
+ - 레포의 프로젝트 스킬·`AGENTS.md`·`.claude/rules/` 에 문서 갱신 규칙(어떤 코드가 바뀌면
+ 어떤 문서를 고치는지)이 있으면 읽고 그대로 따른다.
- ### 2. 문서의 검증 가능한 주장 수집
+ ### 2. 드리프트 뽑기 — 스크립트 먼저
- 대상: `README*`, `AGENTS.md`, `CLAUDE.md`, 각 디렉터리 `README.md`, 스킬/에이전트 문서.
+ 손 grep 보다 스크립트가 먼저다. 사람이 짠 정규식은 하위 프로젝트의 같은 이름 경로
+ (`ews-v3/web/src` 를 가리키는 `web/src`)를 지운 경로로 오인한다.
```bash
- grep -rn '`[^`]*/`\|버전\|기본값\|default\|v[0-9]\+\.[0-9]' README*.md docs/ 2>/dev/null
+ S=<이 스킬>/scripts/find_stale_refs.py
+ python3 $S --removed-since <기준> # 지워지거나 옮겨진 경로를 가리키는 줄
+ python3 $S # 전체 존재 검사(첫 조각이 레포에 있는 경로만)
+ python3 $S --exclude 'model-source/*' --json # 보존본 제외, 기계 처리용
```
- 특히 낡기 쉬운 것: **디렉터리 트리 블록**(신규 산출물 누락), **버전 표기**,
- **"자동으로 ~한다" 류 동작 서술**, **지원 매트릭스**.
+ - 추적 중인 문서(`*.md`·`*.yaml`·`*.toml`·`AGENTS*`·`CLAUDE*` 등)만 본다. 코드의 경로
+ 문자열은 빌드·테스트 몫이다.
+ - 전체 존재 검사는 첫 경로 조각이 지금 레포에 있는 토큰만 본다(다른 레포 경로 소음을 줄이려고).
+ 최상위 폴더를 통째로 지웠다면 반드시 `--removed-since` 로 잡는다.
+ - 레포 어딘가에 실제로 있는 경로(하위 프로젝트 기준 상대경로, `docs/12` 같은 번호 축약)는
+ 빼고 보고한다. 옮겨진 경로는 `renamed -> 새 경로` 로 알려 준다.
+ - 종료 코드는 `current` 가 있으면 1, `history` 만 남으면 0, git·인자 오류는 2 다.
+ 1 은 스크립트가 고장 났다는 뜻이 아니라 고칠 줄이 있다는 뜻이다. `--strict` 는 `history` 도 1 로 센다.
+ - 스크립트가 못 잡는 드리프트는 따로 확인한다. 서술 종류마다 근거 원천이 정해져 있고,
+ **문서끼리 맞추지 않는다**.
- ### 3. 주장별 대조
+ | 서술 | 근거 원천 |
+ |---|---|
+ | 환경변수 이름 | 설정을 읽는 코드(`os.Getenv`·config 로더), `.env.example` |
+ | 포트·컨테이너·헬스체크 | Quadlet `*.container`·compose 의 `HealthCmd`·`PublishPort`, 실제 `podman ps`/`docker ps` |
+ | 실행 명령·CI 잡 | `package.json` scripts, `Makefile`, CI 설정 파일 |
+ | 의존성·버전 | `go.mod`·`package.json`·lock 파일 |
+ | 개수·수치("테이블 37개") | 실제 조회 결과와 그 날짜(DB 쿼리·`find`·`grep -c`) |
+ | 트래커 동작(자동 클로즈 등) | 직전 이슈·MR 의 실제 state |
+ | CLI 플래그·기본값 | `<cmd> --help` 실행 결과(문서 인용 금지) |
+ | 도구 버전 | `<cmd> --version` 실측 + **실측 일자 병기** |
+ | 동작("자동 로드한다") | 해당 도구 **공식문서 URL**. 없으면 "문서 근거 없음"으로 표기 |
+ | 게이트 동작 | 실제로 실행해서 exit code 확인 |
- | 주장 유형 | 검증 방법 |
- |---|---|
- | 경로·파일 존재 | `ls` / `find` — 실제 생성물 기준, 소스 트리 아님 |
- | CLI 플래그·기본값 | `<cmd> --help` 실행. 문서 인용 금지, 출력이 근거 |
- | 도구 버전 | `<cmd> --version` 실측 + **실측 일자 병기** |
- | 동작("자동 로드한다") | 해당 도구 **공식문서 URL**. 없으면 "문서 근거 없음"으로 표기 |
- | 수치·임계값 | 코드에서 grep 하거나 실제 산출물 측정(`wc -c` 등) |
- | 게이트 동작 | 실제로 실행해서 exit code 확인 |
+ 특히 낡기 쉬운 것: **디렉터리 트리 블록**(신규 산출물 누락 — 링크가 아니라 코드블록 안
+ 텍스트라 링크 체커도 못 잡는다), **버전 표기**, **"자동으로 ~한다" 류 동작 서술**, **지원 매트릭스**.
- ### 4. 다국어·짝 파일 동시 갱신 (필수)
+ - 고친 서술은 레포 전체에서 같은 서술을 다시 찾는다(`git grep`). zsh 에서 `grep --include`
+ 를 쓰면 glob 을 따옴표로 감싼다(`--include='*.md'`) — 안 그러면 `no matches found` 로 멈춘다.
+ - `AGENTS.yaml` 이 있으면 레포의 검증기(`scripts/check-agents-yaml.sh`)를 돌린다.
- 한쪽만 고치면 나머지가 stale 이 되는데 **어떤 게이트에도 안 걸린다.**
+ #### 레포별 범위 — `AGENTS.yaml` 의 `x-doc-sync`
- ```bash
- ls README*.md # 다국어 README 전량
- ls presets/lang-en/ 2>/dev/null # 언어 오버레이 존재 여부
+ 레포마다 「고치지 않는 시점 기록」과 「아예 안 보는 경로」가 다르다. 레포 루트
+ `AGENTS.yaml` 에 적어 두면 스크립트가 읽는다(`yd-agents-yaml` 규약의 `x-` 섹션).
+
+ ```yaml
+ x-doc-sync:
+ history: # 찾아도 history 로만 센다 — 고치지 않는 기록
+ - CHANGELOG.md
+ - docs/superpowers/{plans,specs}/**
+ - .claude/memory/archive/**
+ exclude: # 훑지 않는다 — 원본 사본·생성 데이터
+ - data/manual/**
```
- - README 를 고쳤으면 존재하는 언어판 전부를 **같은 커밋**에서. 이 저장소 기준
- `README.md`(영문) · `README.ko.md` · `README.zh.md` · `README.ja.md` 4종이다.
- - `.claude/**` 베이스 파일을 고쳤으면 `presets/lang-en/` 의 대응 파일도 같은 커밋에서.
- - 번역이 아니라 **같은 사실의 각 언어판** — 수치·버전·경로·표 구조는 동일하게 유지한다.
- - 언어별로 원문이 달라 일괄 치환이 깨진다. 파일마다 `grep -n` 으로 교체 대상을 먼저 확인한다.
+ `*`·`**`(둘 다 `/` 를 넘는다)·`{a,b}` 를 쓴다. 섹션이 없으면 기본값(CHANGELOG·`archive/`
+ 는 이력, 잠금 파일·`node_modules` 등은 제외)으로 돈다. 레포에 이 섹션을 처음 넣을 때는
+ `AGENTS.md` 에 「문서 현행화는 `docs-sync` 를 쓴다」 한 줄도 같이 둔다.
+ PyYAML 이 없어도 위 모양(블록 목록·흐름 목록)은 읽는다. 깨진 `AGENTS.yaml` 은 경고만 내고 기본값으로 돈다.
- ### 5. 게이트 실행
+ ### 3. 분류 — 현행 지시와 시점 기록을 가른다
+ 찾은 줄을 셋으로 나눈다. 스크립트의 `current`/`history` 는 낱말 기반 추정이니
+ **줄을 직접 읽고** 정한다.
+
+ | 분류 | 예 | 처리 |
+ |---|---|---|
+ | 현행 지시 | "서버는 `backend/cmd/server` 로 띄운다", 규칙 파일의 `paths:` | 실제에 맞게 고친다. 대상이 없어졌으면 문장을 지우거나 새 위치로 바꾼다 |
+ | 시점 기록 | CHANGELOG, "2026-09-21 커밋 `e59d98b` 기준", 이슈 번호가 붙은 결정 기록, 지난 계획·스펙(`plans/`·`specs/`), 실행 로그(`runs/`), 메모리 `archive/`, 보존용 원본 사본 | **고치지 않는다.** 현행 지시처럼 읽혀 오해를 부르면 "(#N 에서 제거)" 같은 표지만 붙인다 |
+ | 생성물 | 스크립트가 만든 HTML·SVG·코드 | 직접 고치지 않는다. 생성기(템플릿·스크립트)를 고치고 다시 돌린다 |
+
+ - 설계 결정 기록(ADR·D-엔트리)이 있는 레포에서 구조가 바뀌었으면 결정 항목을 하나
+ 더하고, 옛 서술은 그 항목을 가리키게 표시한다. 옛 결정 본문을 다시 쓰지 않는다.
+ - 메모리 파일은 경로 참조만 고치고, 사실 자체의 낡음은 `memory-factcheck` 로 넘긴다.
+
+ ### 4. 고치기
+
+ - **근거를 확인한 것만 고친다.** 새 경로·명령·값은 실제 파일을 열거나 명령을 돌려 확인한
+ 뒤 적는다. 확인 못 한 줄은 고치지 말고 보고서의 「확인 필요」에 둔다.
+ - 지운 기능을 설명하던 절은 통째로 지운다. 빈 껍데기 문장("~는 없다")을 여러 군데
+ 남기지 말고, 사라진 사실은 한 곳(README·결정 기록)에만 남긴다.
+ - 문서 갱신 규칙이 있는 파일(규칙 표, 스킬 목록, 인덱스)은 표와 실제 파일 목록을 함께 맞춘다.
+ - **고친 문장은 항상 `yd-writer-kr` 로 정리한다.** 경로만 바꾸면 앞뒤 문장이 어긋나기
+ 쉽다. 고친 줄과 그 문단을 그 스킬 규칙으로 다시 읽고 다듬는다. 문체는 그 문서의 것을
+ 따르고, 고치지 않은 문단까지 손대지 않는다.
+ - **다국어·짝 파일은 같은 커밋에서 함께 고친다(필수).** 한쪽만 고치면 나머지가 stale 이
+ 되는데 어떤 게이트에도 안 걸린다. `ls README*.md` 로 언어판 전량을, `presets/lang-en/` 같은
+ 언어 오버레이가 있으면 대응 파일까지 고친다. 번역이 아니라 **같은 사실의 각 언어판**이라
+ 수치·버전·경로·표 구조는 동일하게 둔다. 언어마다 원문이 달라 일괄 치환이 깨지므로 파일마다
+ `grep -n` 으로 교체 대상을 먼저 확인한다.
+ - 고친 파일이 많으면 파일 범위를 겹치지 않게 나눠 서브에이전트에 맡겨도 된다. 사실
+ 업데이트(예: 운영 철거 완료)가 생기면 즉시 모든 서브에이전트에 전달한다.
+
+ ### 5. 검증
+
```bash
- python3 .claude/scripts/knowledge_graph.py --check # 깨진 링크 0 확인
+ python3 $S --removed-since <기준> # current 0 이거나, 남은 줄마다 둔 이유가 있다
+ <레포 검증기들> # AGENTS.yaml 검증기, 링크 검사(python3 .claude/scripts/knowledge_graph.py --check) 등
+ <레포 빌드·테스트> # 문서와 함께 바뀐 스크립트·설정이 있으면
```
- 문서만 고쳤어도 테스트 스위트를 한 번 돌린다 — 문서에 인용된 명령·경로가 테스트와
- 어긋나 있으면 여기서 드러난다.
+ 남은 `current` 는 줄마다 왜 두는지(다른 레포 경로, 의도된 이력) 한 줄로 적는다.
### 6. 보고
- 정정한 주장을 **`이전 → 이후 + 근거`** 형태로 나열한다. "README 를 갱신했다" 같은
- 요약만 남기지 않는다. 확인 못 해 "미검증"으로 남긴 항목도 함께 보고한다.
+ 채팅에는 짧게, 상세는 이슈·MR 본문에 둔다. 보고서와 이슈·MR 본문도 `yd-writer-kr` 로 쓴다.
- ## 완료 기준
+ ```
+ ## 문서 현행화 — <기준>..HEAD
+ - 고친 것: <파일 N개> — 주장마다 `이전 → 이후 + 근거`("README 를 갱신했다" 같은 요약만 남기지 않는다)
+ - 기록으로 둔 것: <파일·줄> — <이유>
+ - 확인 필요: <줄> — <무엇을 확인해야 하는지>
+ - 대조하지 못한 범위: <폴더·문서 종류> — <이유(접근 불가·근거 원천 없음·시간)>
+ - 검증: find_stale_refs current <n>건(사유 명시), <검증기> 통과
+ ```
- - 문서의 모든 검증 가능한 주장에 근거가 있거나 "미검증" 표시가 있다
- - 다국어·오버레이 짝 파일이 같은 커밋에 포함됐다
- - 링크 체커 0 broken, 테스트 스위트 통과
+ 커밋·MR 은 레포 워크플로(이슈 → 브랜치 → PR/MR)로 올린다. 문서 현행화는 코드 변경과 같은 MR 에 넣는 것이
+ 원칙이다(코드를 바꾼 MR 이 문서도 같이 고친다). 이미 머지된 변경을 뒤따라 맞출 때만
+ 별도 이슈로 연다.
+ ## 완료 조건
+
+ - `find_stale_refs.py --removed-since <기준>` 의 `current` 가 0 이거나, 남은 줄마다 둔 이유가 보고서에 있다.
+ - 고친 서술마다 근거 파일·명령 결과를 확인했다.
+ - 시점 기록과 생성물은 직접 고치지 않았다.
+ - 고친 문장과 보고서·이슈·MR 본문을 `yd-writer-kr` 로 정리했다.
+ - 다국어·언어 오버레이 짝 파일이 같은 커밋에 들어 있다.
+ - 레포의 문서 검증기(링크 체커 0 broken 포함)와, 함께 바뀐 스크립트의 테스트가 통과한다.
+ - 보고서·MR 본문에 대조하지 못한 범위를 적었다(없으면 「없음」). 빠뜨린 폴더가 다음 드리프트가 된다.
+
## Learned warnings
- - 낡은 서술을 **삭제**로 처리하면 "왜 없어졌는지" 추적이 끊긴다 — 실측 일자와 함께
- "미검증"으로 남기는 편이 낫다.
- - 디렉터리 트리 블록이 가장 자주 낡는다. 신규 산출물이 추가된 커밋에서 트리를 안 고치면
- 링크 체커도 못 잡는다(링크가 아니라 코드블록 안 텍스트라서).
+ - (2026-10-24) agents-scaffold 의 `docs-sync` 와 doksam-skills 의 `yd-doc-sync` 를 하나로 합쳤다. 드리프트 추출(`find_stale_refs.py`)·현행/기록 분류는 yd-doc-sync, 주장 단위 대조·"미검증" 표기·다국어 짝 파일 동시 갱신·링크 체커 게이트는 docs-sync 에서 왔다 (agents-scaffold #78).
+ - (2026-10-24) 낡은 서술을 **삭제**로 처리하면 "왜 없어졌는지" 추적이 끊긴다 — 실측 일자와 함께 "미검증"으로 남기는 편이 낫다.