docs: 문서-코드 드리프트 17건을 고치고 게이트로 묶는다 - #64
Merged
Merged
Conversation
전면 대조에서 나온 것들이다. 가장 아픈 건 CLI 플래그 파리티 테스트가 SKILL.md 하나만 봤다는 점이다 — 그 사이 `--fold-with-tree`가 npm README와 번역 4종에서 조용히 빠져 있었고(플래그를 만든 #14이 루트 README와 SKILL.md만 갱신했다), 게이트가 한 문서만 보는 한 나머지는 아무도 지키지 않는다. 그래서 테스트를 docs-flags-parity로 이름을 바꿔 일곱 문서 전부를 대조하게 했다. 이 테스트는 고치기 전 상태에서 정확히 그 다섯 문서를 빨간불로 잡는다. 틀린 설명: README 아키텍처가 agent skill을 apps/viewer 소속으로 적었지만 실제로는 레포 루트 skills/에 살고 build.ts가 dist/로 복사한다(번역 4종 동일). trees "46 src"는 trees만 style.css를 포함해 센 값이라 45로 고치고, 무엇을 세는지 규칙과 재계산 명령을 함께 박았다. 엔진 규모 27k는 실측 29,482줄이다. diff.ts:220-221은 221-222다. 모순: CLAUDE.md가 pr-check을 세 곳에서 다르게 열거했다(한 곳은 e2e 누락). README의 커버리지 제외 목록은 여섯 중 셋만 적고 "의도적으로 제외된 것"이라 단정했다 — scripts/**와 스펙 자신이 빠져 있었다(번역 4종 동일). 누락: WHAT 트리에 skills/·docs/·.github/·플러그인 매니페스트·CHANGELOG.md· bunfig.toml이 없었다. 125행이 "동기화 필수"라고 계약을 거는 대상과 83행이 "레포 루트에 있다"고 계약을 거는 파일이 지도에 없는 상태였다. prewarm.ts, bunfig preload의 happy-dom 함정, 배포물이 deps 0인 전량 번들이라는 사실도 어디에도 없었다. 데드코드: isDiffViewerDisabled/DIFFDECK_DISABLE을 지웠다. 호출부가 한 번도 없었고 유일한 참조가 자기 테스트라 커버리지 100%가 그대로 유지됐다 — 게이트로는 원리적으로 안 드러나는 종류였다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1
앞 커밋을 적대적으로 재검증한 결과다. 가장 나쁜 건 첫 번째 — 맞는 걸 틀리게 바꿔놨다. - `diff.ts:220-221`을 221-222로 "고쳤"는데 원래가 맞았다. `resolve(repo)`가 220, `resolve(root, path)`가 221이다. 되돌린다. - `--fold-with-tree` 드리프트의 경로를 잘못 짚었다. #14은 루트 README와 CLAUDE.md를 갱신했고 SKILL.md는 손대지 않았다 — SKILL.md는 파리티 테스트를 만든 #24이 뒤늦게 채웠다. 사실관계가 오히려 논지를 강화한다: 게이트가 감시하는 문서만 따라잡혔다. - 배포 tarball을 "files 필드대로 셋뿐"이라 적었지만 `npm pack --dry-run`은 9개다 — npm이 README.md와 package.json을 files와 무관하게 강제로 싣는다. 같은 문서가 apps/viewer/README.md를 "npm 패키지 페이지"라 부르는 근거가 바로 그 강제 포함이라, 앞 문장이 뒷 문장을 부정하고 있었다. - WHAT 트리에 pr-check을 "5잡 게이트"라 적었는데, 같은 문서 아래쪽이 required status checks가 비어 있다고 실측으로 말한다. 트리만 읽은 사람은 정반대를 배운다. - happy-dom preload 함정의 "21건"은 처음 밟았을 때 값이고 지금은 58건이다. 개수는 스위트 크기의 함수라 상수로 박으면 안 된다 — bunfig.toml 주석도 같이 고쳤다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1
원어민 관점 리뷰에서 나온 것들이다. 대부분 앞 커밋이 새로 만든 흠이다. - 아키텍처 코드블록은 ko·ja·zh에서 원래 100% 영어인데 내가 현지어 두 줄을 끼워 넣어 관례를 깼다. 영어로 되돌린다. es는 반대로 블록 전체가 스페인어이므로 그대로 두되, `el agent skill … copiado`의 성·용어가 같은 파일 106행의 `la skill de agente`와 어긋나 `la … copiada`로 고친다. - 29.5k를 백틱 친 `CodeView`에 붙여 놓아, grep하면 3,563줄이 나오는 파일과 8배 어긋났다. 다섯 README 전부에서 `packages/diffs`임을 밝힌다. - ko 표가 네 행에서 "파일 트리"라 부르는 위젯을 새 행만 "사이드바"라 불렀다. 용어를 맞추고, 동작도 단방향(트리를 접으면 diff가 따라 접힌다)으로 적는다. - zh `将…同步`는 기동 시 1회 동작으로 읽힌다. 지속 모드이므로 `保持同步`. - 무생물에 붙은 재귀대명사를 고친다: ko `스펙 자신` → `스펙 파일 자체`, zh `测试自身` → `测试文件本身`. - es는 열거 마지막 `y` 앞의 쉼표를 뺀다(RAE). 소수점도 스페인어 관례상 마침표가 아니라서 `~29.5k` → `~29 500`. - es `--fold-with-tree` 설명이 "folds"를 흘려 "diff와 동기화"로 읽혔다. `el plegado del diff`로 무엇과 동기화되는지 밝힌다. 덤으로, npm README만 `XDG_CACHE_HOME`을 적고 나머지 다섯은 `~/.cache`만 말하고 있었다 — 이 PR이 고치는 것과 같은 종류의 드리프트라 함께 맞춘다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1
게이트의 한계를 과장한 게 제일 나쁘다 — 이 PR이 고치는 병과 같은 종류다. - 새 파리티 게이트를 "추가·변경·삭제를 잡는다"고 적었는데 단방향이다. HELP의 각 플래그가 문서에 있는지만 보므로 플래그를 지우면 문서에 남은 유령 플래그가 그대로 통과한다. Options 블록만 읽어서 install-skill의 --codex/--project도 게이트 밖이다. 무엇을 증명하지 않는지 명시한다. - pr-check을 84행에서 "다섯 잡"으로 통일해놓고 정작 그걸 설명하는 89행은 여섯 항목을 잡으로 나열한 채 뒀다. 같은 커밋이 만든 모순이다. - e2e fixtures를 세 파일로 적었지만 넷이다. #43이 추가한 drag.ts가 빠져 있었는데, 이건 grab 계열 두 스펙이 공유하는 실측 튜닝값의 단일 지점이라 목록에 없으면 재튜닝할 곳을 못 찾는다. - 파일 수 규칙에서 themes/*.json을 "제외"라 적었지만 src/ 밖이라 애초에 세어지지 않는다. 규칙이 닿지도 않는 걸 제외라 부르면 규칙이 흐려진다. - parity 하니스 열거에 index.html이 빠졌다 — 문서가 열라고 지시하는 파일이다. 덤: tsconfig.base.json의 include에 남은 bin/**/*.ts도 vestigial이라 JSX 항목에 함께 적는다. Plan 5가 CLI를 apps/viewer에 두면서 bin/은 끝내 만들어지지 않았고, tsc는 매칭 없는 glob을 조용히 넘긴다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1
Critical 하나가 하필 "번들에 뭐가 들었는지 확인하는 법"을 가르치는 문단에
있었다. 그 문단을 믿고 grep한 사람이 정반대 결론을 내게 된다.
- worker.js가 "shiki와 문법 전량을 품는다"고 적었지만 문법은 0이다.
worker.ts가 createHighlighterCore({themes:[], langs:[]})로 빈 채 뜨고
문법은 WorkerPoolManager가 postMessage로 밀어넣는다. 실측으로
main.js 298 : worker.js 0 (source.ts 기준). 10.9MB 대 836KB 격차가
정확히 그 차이다. grep -c를 쓰지 말라는 주의도 함께 적는다 — 미니파이
번들은 사실상 한 줄이라 298이 1로 보인다.
- 새 게이트가 "언급"을 증명하지 "위치"를 증명하지 않는다. 표의 행을 지우고
같은 코드 스팬을 산문으로 옮겨도 통과한다(리뷰가 mutation으로 확인).
표 문법에 앵커를 걸지 않는 이유까지 테스트 주석에 남긴다 — 번역 4종의
컬럼 폭이 제각각이고 SKILL.md는 표가 아니라, 앵커를 걸면 게이트가 먼저
부서진다.
- CLAUDE.md 자신이 여덟 번째 플래그 기술처인데 DOCS에 없다. --port·
--no-open을 안 다뤄서 넣으면 빨간불이 나는 의도적 제외다. 다음 사람이
"빠뜨렸다"고 판단해 추가하지 않도록 이유를 적는다.
- 파일 읽기를 describe 본문에서 test 콜백 안으로 옮긴다. 경로가 틀리면
테스트 등록 전에 throw해서 "문서 X가 없다"가 아니라 수집 크래시로
보였다 — 가드 두 개조차 안 돌았다.
- preload 플러그인을 "빌드와 같은 것"이라 적었지만 같은 모듈의 두 export다
(runtime/bundler). WHAT 트리가 이미 "런타임/번들러 2분리"라 적고 있어
두 줄이 서로 어긋났다.
- 21건 설명이 "bunfig 주석이 적은"이라는 옛 상태를 가리키고 있었다.
덤: 다섯 README의 "런타임 외부 의존성" 줄이 workspace 그래프를 말하는
건데, 이제 CLAUDE.md가 "설치 시 resolve되는 게 없다"고 못 박아 나란히
읽으면 어긋나 보인다. 한 구절로 둘을 잇는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CLAUDE.md와 README 계열(루트·npm·번역 4종)을 코드·CI·리포 설정과 전면 대조해 나온 드리프트 17건을 고치고, 재발한 경로를 게이트로 묶었다.
왜 이게 필요했나
가장 아픈 건 게이트가 문서 하나만 보고 있었다는 점이다.
skill-flags-parity.test.ts는cli.ts의HELP와SKILL.md만 대조했는데, CLI 표면을 사람에게 되풀이해 말하는 문서는 실제로 일곱이다. 그 사이--fold-with-tree가 npm 패키지 페이지(apps/viewer/README.md)와 번역 4종에서 조용히 빠져 있었다 — 플래그를 만든 #14이 루트 README와 SKILL.md만 갱신했기 때문이고, 게이트는 그걸 볼 방법이 없었다.바뀐 것
게이트 (재발 방지)
skill-flags-parity.test.ts→ **docs-flags-parity.test.ts**로 이름을 바꾸고 대상을 일곱 문서 전부로 넓혔다. 플래그는 문서에서 항상 코드 스팬으로 적히므로`--flag뒤에 백틱이나 공백을 요구하는 정규식으로 대조한다(산문 속 우연한 일치와 접두 오매칭을 둘 다 막는다).이 테스트는 고치기 전 상태에서 정확히 그 다섯 문서를 빨간불로 잡는다 (RED 확인 후 GREEN으로 전환):
틀린 설명
README.md아키텍처 (+번역 4종)apps/viewer소속skills/에 산다.build.ts:68-69가dist/skills/로 복사할 뿐CLAUDE.mdWHAT46 srcstyle.css를 포함해 센 값이었다README.md·CLAUDE.md(2곳)·번역 4종~27k linespackages/diffs/src테스트 제외.ts합계)CLAUDE.mdcwd 항목diff.ts:220-221221-222파일 수는 세는 규칙이 패키지마다 달라 틀렸으므로, 무엇을 세는지와 재계산 명령을 문서에 박았다. 그 명령이 네 숫자(18/14/144/45)를 전부 재현하는 것을 확인했다.
모순
CLAUDE.md가pr-check을 세 곳에서 다르게 열거했다 — 기여 워크플로 항목만 e2e가 빠진 옛 목록이었다(다른 두 곳은 e2e 포함, "다섯 잡"). 통일했다.README.md(+번역 4종)의 커버리지 제외 목록이 여섯 중 셋만 적고 "의도적으로 제외된 것"이라 단정했다.scripts/**와 스펙 자신(*.test.ts·e2e/**)이 빠져 있었다.누락
skills/·docs/·.github/workflows/·.claude-plugin/·.codex-plugin/·CHANGELOG.md·bunfig.toml이 없었다. 125행이 "동기화 필수"라고 계약을 거는 대상과 83행이 "레포 루트에 있다"고 계약을 거는 파일이 지도에는 없는 상태였다.server/prewarm.ts—cli.ts가 기동 직후/api/diff를working·base순차로 호출해 캐시를 데우는 경로가 어디에도 없었다. 순차인 이유(BUILD_CONCURRENCY=8이 호출당이라 겹치면 서브프로세스 버스트가 배가 된다)까지 적었다 — "Loading…" 항목의 재시도 1회 제한과 같은 근거다.bunfig.toml의 preload 함정 — happy-dom 전역 등록이 preload에서 의도적으로 빠져 있다는 사실(전역 등록은 Node fetch/http를 런 전체에서 갈아치워 실제 HTTP 서버 테스트를 무너뜨린다)이 bunfig 주석에만 살아 있었다.apps/viewer/package.json에dependencies가 없는 게 의도라는 것과, 그래서 새 런타임 import를 넣을 때 적을 곳이 없다는 함의.데드코드
config.ts의isDiffViewerDisabled/DIFFDECK_DISABLE을 지웠다. 호출부가 한 번도 없었고(유일한 참조가 자기 테스트) 그래서 커버리지 100%가 그대로 유지돼 게이트로는 원리적으로 안 드러나는 종류였다.CLAUDE.md의 "cc-statusline 잔재 제거됨" 항목에 이 사례를 근거와 함께 남겼다 — 커버리지 초록은 "쓰인다"는 증거가 아니다.검증
e2e의 1건은
worker-highlight.e2e.ts:30"first entry into the overscan window must not freeze the frame"으로, 프레임 예산을 재는 성능 테스트다. 로컬에서 다른 무거운 작업과 동시에 돌린 실행이었고, 단독 재실행 시 6.0초로 통과한다(타임아웃 15초). 이 PR의 런타임 변경은config.ts에서 호출부 없는 export 하나를 지운 것뿐이라 워커 하이라이트 경로와 접점이 없다. CI의 e2e 잡이 독립 러너에서 판정하게 두는 것이 맞다고 본다.dist/cli.js가 외부 deps 0, shiki는 뷰어·워커 번들)은bun run build후 산출물을 직접 열어 확인했다.함께 확인한 것 (변경 없음)
루트의 untracked
AUDIT-2026-07-23.md에 남아 있던 항목을 대조했다: P0-1(비-ASCII 파일명 →diff.ts가-z파싱 +korean-filename.e2e.ts), P0-2(happy-dom 20.11.1), P1-1(CLAUDE.md 현행화), P1-2(findBar.destroy()), P2-1(패키지 4종), P2-2(매니페스트 버전 release-please 배선) 전부 해소돼 있다. 남은 건 명시적으로 선택 사항인 둘뿐이다 — lint 경고 정리와setup-bun버전 핀(정책 결정 필요). 그 파일은 이 PR에 포함하지 않았다.🤖 Generated with Claude Code
https://claude.ai/code/session_01G1vWAequwbToDppRceT6C1